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)
22 /*** Generic transformed page ***/
24 class xform_page : public page {
28 void render(out_context *out, pdf_matrix xform);
29 xform_page(page *p, pdf_matrix xf);
32 xform_page::xform_page(page *p, pdf_matrix xf)
38 BBox media(p->width, p->height);
40 width = media.width();
41 height = media.height();
47 void xform_page::render(out_context *out, pdf_matrix parent_xform)
49 orig_page->render(out, xform * parent_xform);
54 class move_cmd : public cmd_exec {
57 vector<page *> process(vector<page *> &pages);
60 vector<page *> move_cmd::process(vector<page *> &pages)
67 out.push_back(new xform_page(p, m));
72 static const arg_def move_args[] = {
73 { "x", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
74 { "y", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
78 static cmd_exec *move_ctor(cmd *c)
80 move_cmd *m = new move_cmd;
81 m->x = c->args.at(0)->as_double(0);
82 m->y = c->args.at(1)->as_double(0);
88 class scale_cmd : public cmd_exec {
90 double x_factor, y_factor;
91 vector<page *> process(vector<page *> &pages);
94 vector<page *> scale_cmd::process(vector<page *> &pages)
100 m.scale(x_factor, y_factor);
101 out.push_back(new xform_page(p, m));
106 static const arg_def scale_args[] = {
107 { "x", AT_DOUBLE | AT_MANDATORY | AT_POSITIONAL },
108 { "y", AT_DOUBLE | AT_POSITIONAL },
112 static cmd_exec *scale_ctor(cmd *c)
114 scale_cmd *s = new scale_cmd;
115 s->x_factor = c->args.at(0)->as_double(1);
116 s->y_factor = c->args.at(1)->as_double(s->x_factor);
122 class rotate_cmd : public cmd_exec {
125 vector<page *> process(vector<page *> &pages);
128 vector<page *> rotate_cmd::process(vector<page *> &pages)
140 m.shift(0, p->width);
144 m.shift(p->width, p->height);
148 m.shift(p->height, 0);
153 out.push_back(new xform_page(p, m));
158 static const arg_def rotate_args[] = {
159 { "angle", AT_INT | AT_MANDATORY | AT_POSITIONAL },
163 static cmd_exec *rotate_ctor(cmd *c)
165 rotate_cmd *r = new rotate_cmd;
166 r->deg = c->args.at(0)->as_int(0) % 360;
170 die("Rotate requires a multiple of 90 degrees");
176 class flip_cmd : public cmd_exec {
180 vector<page *> process(vector<page *> &pages);
183 vector<page *> flip_cmd::process(vector<page *> &pages)
192 m.shift(0, p->height);
197 m.shift(p->width, 0);
199 out.push_back(new xform_page(p, m));
204 static const arg_def flip_args[] = {
210 static cmd_exec *flip_ctor(cmd *c)
212 flip_cmd *f = new flip_cmd;
213 f->horizontal = c->args.at(0)->as_int(0);
214 f->vertical = c->args.at(1)->as_int(0);
215 if (!f->horizontal && !f->vertical)
216 die("Flip has no direction specified");
222 class select_cmd : public cmd_exec {
225 vector<page *> process(vector<page *> &pages);
228 static int validate_page_index(vector<page *> &pages, int idx)
230 if (idx >= 1 && idx <= (int) pages.size())
232 if (idx <= -1 && idx >= (int) -pages.size())
233 return idx + pages.size();
234 die("Page index %d out of range", idx);
237 vector<page *> select_cmd::process(vector<page *> &pages)
240 for (auto pb: pipe->branches)
242 vector<page *> selected;
243 for (auto ps: pb->selectors)
245 int f = validate_page_index(pages, ps.from);
246 int t = validate_page_index(pages, ps.to);
247 int step = (f <= t) ? 1 : -1;
248 for (int i=f; f<=t; f += step)
249 selected.push_back(pages[i]);
251 auto processed = run_command_list(pb->commands, selected);
252 for (auto p: processed)
258 static cmd_exec *select_ctor(cmd *c)
260 select_cmd *r = new select_cmd;
267 class apply_cmd : public cmd_exec {
270 vector<page *> process(vector<page *> &pages);
273 static pipeline_branch *find_branch(pipeline *pipe, vector <page *> &pages, int idx)
275 for (auto pb: pipe->branches)
276 for (auto ps: pb->selectors)
278 int f = validate_page_index(pages, ps.from);
279 int t = validate_page_index(pages, ps.to);
280 if (f <= idx && idx <= t || t <= idx && idx <= f)
286 vector<page *> apply_cmd::process(vector<page *> &pages)
293 pipeline_branch *pb = find_branch(pipe, pages, cnt);
298 auto processed = run_command_list(pb->commands, tmp);
299 for (auto q: processed)
310 static cmd_exec *apply_ctor(cmd *c)
312 apply_cmd *r = new apply_cmd;
319 class modulo_cmd : public cmd_exec {
323 vector<page *> process(vector<page *> &pages);
326 vector<page *> modulo_cmd::process(vector<page *> &pages)
329 int tuples = ((int) pages.size() + n - 1) / n;
331 for (int tuple=0; tuple < tuples; tuple++)
333 debug("# Tuple %d", tuple);
335 for (auto pb: pipe->branches)
338 for (auto ps: pb->selectors)
342 int step = (f <= t) ? 1 : -1;
343 for (int i=f; i<=t; i += step)
348 else if (i < 0 && i >= -n)
349 j = (tuples-1-tuple)*n + (-i) - 1;
351 die("Modulo: invalid index %d", i);
352 if (j < (int) pages.size())
353 tmp.push_back(pages[j]);
356 page *ref_page = pages[tuple*n];
357 tmp.push_back(new empty_page(ref_page->width, ref_page->height));
361 auto processed = run_command_list(pb->commands, tmp);
362 for (auto q: processed)
371 static const arg_def modulo_args[] = {
372 { "n", AT_INT | AT_MANDATORY | AT_POSITIONAL },
376 static cmd_exec *modulo_ctor(cmd *c)
378 modulo_cmd *m = new modulo_cmd;
379 m->n = c->args.at(0)->as_int(0);
381 die("Modulo must have n > 0");
388 class draw_bbox_cmd : public cmd_exec {
390 vector<page *> process(vector<page *> &pages);
393 class draw_bbox_page : public page {
396 void render(out_context *out, pdf_matrix xform);
397 draw_bbox_page(page *p) : page(p) { orig_page = p; }
400 void draw_bbox_page::render(out_context *out, pdf_matrix xform)
402 orig_page->render(out, xform);
405 xform.to_string() + " cm " +
407 bbox.to_rect() + " re S " +
411 vector<page *> draw_bbox_cmd::process(vector<page *> &pages)
415 out.push_back(new draw_bbox_page(p));
419 static cmd_exec *draw_bbox_ctor(cmd *c UNUSED)
421 draw_bbox_cmd *m = new draw_bbox_cmd;
425 /*** Command table ***/
427 const cmd_def cmd_table[] = {
428 { "null", no_args, 0, null_ctor },
429 { "move", move_args, 0, move_ctor },
430 { "scale", scale_args, 0, scale_ctor },
431 { "rotate", rotate_args, 0, rotate_ctor },
432 { "flip", flip_args, 0, flip_ctor },
433 { "select", no_args, 1, select_ctor },
434 { "apply", no_args, 1, apply_ctor },
435 { "modulo", modulo_args, 1, modulo_ctor },
436 { "draw_bbox",no_args, 0, draw_bbox_ctor },
437 { NULL, NULL, 0, NULL }