4 * (c) 2018 Martin Mares <mj@ucw.cz>
15 class null_cmd : public cmd_exec {
16 vector<page *> process(vector<page *> &pages) override { return pages; }
19 static const arg_def no_args[] = {
23 static cmd_exec *null_ctor(cmd *c UNUSED)
28 /*** Generic transformed page ***/
30 class xform_page : public page {
34 void render(out_context *out, pdf_matrix xform) override;
35 xform_page(page *p, pdf_matrix xf);
38 xform_page::xform_page(page *p, pdf_matrix xf)
44 BBox media(p->width, p->height);
46 width = media.width();
47 height = media.height();
53 void xform_page::render(out_context *out, pdf_matrix parent_xform)
55 orig_page->render(out, xform * parent_xform);
58 class cmd_exec_simple : public cmd_exec {
59 virtual page *process_page(page *p) = 0;
60 vector<page *> process(vector<page *> &pages) override;
63 vector<page *> cmd_exec_simple::process(vector<page *> &pages)
67 out.push_back(process_page(p));
73 class move_cmd : public cmd_exec_simple {
76 page *process_page(page *p) override
80 return new xform_page(p, m);
84 static const arg_def move_args[] = {
85 { "x", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
86 { "y", AT_DIMEN | AT_MANDATORY | AT_POSITIONAL },
90 static cmd_exec *move_ctor(cmd *c)
92 move_cmd *m = new move_cmd;
93 m->x = c->args.at(0)->as_double(0);
94 m->y = c->args.at(1)->as_double(0);
100 class scale_cmd : public cmd_exec_simple {
102 double x_factor, y_factor;
103 page *process_page(page *p) override
106 m.scale(x_factor, y_factor);
107 return new xform_page(p, m);
111 static const arg_def scale_args[] = {
112 { "x", AT_DOUBLE | AT_MANDATORY | AT_POSITIONAL },
113 { "y", AT_DOUBLE | AT_POSITIONAL },
117 static cmd_exec *scale_ctor(cmd *c)
119 scale_cmd *s = new scale_cmd;
120 s->x_factor = c->args.at(0)->as_double(1);
121 s->y_factor = c->args.at(1)->as_double(s->x_factor);
127 class rotate_cmd : public cmd_exec_simple {
130 page *process_page(page *p) override
139 m.shift(0, p->width);
143 m.shift(p->width, p->height);
147 m.shift(p->height, 0);
152 return new xform_page(p, m);
156 static const arg_def rotate_args[] = {
157 { "angle", AT_INT | AT_MANDATORY | AT_POSITIONAL },
161 static cmd_exec *rotate_ctor(cmd *c)
163 rotate_cmd *r = new rotate_cmd;
164 r->deg = c->args.at(0)->as_int(0) % 360;
168 die("Rotate requires a multiple of 90 degrees");
174 class flip_cmd : public cmd_exec_simple {
178 page *process_page(page *p) override
184 m.shift(0, p->height);
189 m.shift(p->width, 0);
191 return new xform_page(p, m);
195 static const arg_def flip_args[] = {
201 static cmd_exec *flip_ctor(cmd *c)
203 flip_cmd *f = new flip_cmd;
204 f->horizontal = c->args.at(0)->as_int(0);
205 f->vertical = c->args.at(1)->as_int(0);
206 if (!f->horizontal && !f->vertical)
207 die("Flip has no direction specified");
213 class select_cmd : public cmd_exec {
216 vector<page *> process(vector<page *> &pages);
219 static int validate_page_index(vector<page *> &pages, int idx)
221 if (idx >= 1 && idx <= (int) pages.size())
223 if (idx <= -1 && idx >= (int) -pages.size())
224 return idx + pages.size();
225 die("Page index %d out of range", idx);
228 vector<page *> select_cmd::process(vector<page *> &pages)
231 for (auto pb: pipe->branches)
233 vector<page *> selected;
234 for (auto ps: pb->selectors)
236 int f = validate_page_index(pages, ps.from);
237 int t = validate_page_index(pages, ps.to);
238 int step = (f <= t) ? 1 : -1;
239 for (int i=f; f<=t; f += step)
240 selected.push_back(pages[i]);
242 auto processed = run_command_list(pb->commands, selected);
243 for (auto p: processed)
249 static cmd_exec *select_ctor(cmd *c)
251 select_cmd *r = new select_cmd;
258 class apply_cmd : public cmd_exec {
261 vector<page *> process(vector<page *> &pages);
264 static pipeline_branch *find_branch(pipeline *pipe, vector <page *> &pages, int idx)
266 for (auto pb: pipe->branches)
267 for (auto ps: pb->selectors)
269 int f = validate_page_index(pages, ps.from);
270 int t = validate_page_index(pages, ps.to);
271 if (f <= idx && idx <= t || t <= idx && idx <= f)
277 vector<page *> apply_cmd::process(vector<page *> &pages)
284 pipeline_branch *pb = find_branch(pipe, pages, cnt);
289 auto processed = run_command_list(pb->commands, tmp);
290 for (auto q: processed)
301 static cmd_exec *apply_ctor(cmd *c)
303 apply_cmd *r = new apply_cmd;
310 class modulo_cmd : public cmd_exec {
314 vector<page *> process(vector<page *> &pages);
317 vector<page *> modulo_cmd::process(vector<page *> &pages)
320 int tuples = ((int) pages.size() + n - 1) / n;
322 for (int tuple=0; tuple < tuples; tuple++)
324 debug("# Tuple %d", tuple);
326 for (auto pb: pipe->branches)
329 for (auto ps: pb->selectors)
333 int step = (f <= t) ? 1 : -1;
334 for (int i=f; i<=t; i += step)
339 else if (i < 0 && i >= -n)
340 j = (tuples-1-tuple)*n + (-i) - 1;
342 die("Modulo: invalid index %d", i);
343 if (j < (int) pages.size())
344 tmp.push_back(pages[j]);
347 page *ref_page = pages[tuple*n];
348 tmp.push_back(new empty_page(ref_page->width, ref_page->height));
352 auto processed = run_command_list(pb->commands, tmp);
353 for (auto q: processed)
362 static const arg_def modulo_args[] = {
363 { "n", AT_INT | AT_MANDATORY | AT_POSITIONAL },
367 static cmd_exec *modulo_ctor(cmd *c)
369 modulo_cmd *m = new modulo_cmd;
370 m->n = c->args.at(0)->as_int(0);
372 die("Modulo must have n > 0");
379 class draw_bbox_cmd : public cmd_exec {
381 vector<page *> process(vector<page *> &pages);
384 class draw_bbox_page : public page {
387 void render(out_context *out, pdf_matrix xform);
388 draw_bbox_page(page *p) : page(p) { orig_page = p; }
391 void draw_bbox_page::render(out_context *out, pdf_matrix xform)
393 orig_page->render(out, xform);
396 xform.to_string() + " cm " +
398 bbox.to_rect() + " re S " +
402 vector<page *> draw_bbox_cmd::process(vector<page *> &pages)
406 out.push_back(new draw_bbox_page(p));
410 static cmd_exec *draw_bbox_ctor(cmd *c UNUSED)
412 draw_bbox_cmd *m = new draw_bbox_cmd;
416 /*** Command table ***/
418 const cmd_def cmd_table[] = {
419 { "null", no_args, 0, null_ctor },
420 { "move", move_args, 0, move_ctor },
421 { "scale", scale_args, 0, scale_ctor },
422 { "rotate", rotate_args, 0, rotate_ctor },
423 { "flip", flip_args, 0, flip_ctor },
424 { "select", no_args, 1, select_ctor },
425 { "apply", no_args, 1, apply_ctor },
426 { "modulo", modulo_args, 1, modulo_ctor },
427 { "draw_bbox",no_args, 0, draw_bbox_ctor },
428 { NULL, NULL, 0, NULL }