initial setup of thesis repository
[cluster_expansion_thesis.git] / little_helpers / tikz / sketch-0.2.161 / emit.c
blob7770da9c0133cb380c14e9d56a87402b9f541dc9
1 /* emit.c
2 Copyright (C) 2005,2006,2007,2008 Eugene K. Ressler, Jr.
4 This file is part of Sketch, a small, simple system for making
5 3d drawings with LaTeX and the PSTricks or TikZ package.
7 Sketch is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 Sketch is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Sketch; see the file COPYING.txt. If not, see
19 http://www.gnu.org/copyleft */
21 #include <math.h>
22 #include "emit.h"
23 #include "scene.h"
24 #include "version.h"
26 // ---- emit output -----------------------------------------------------------
28 char standard_us_doc_template_file_name_flag[] =
29 "<standard us doc template file name flag>";
30 char standard_euro_doc_template_file_name_flag[] =
31 "<standard euro doc template file name flag>";
33 // concise floating point output
34 // idea of %g but with fixed rather than relative precision
35 // removing excessive 0's often reduces output file size dramatically
36 // and also eases reading
37 char *
38 flt_str_fmt (char *fmt, char *buf, double f)
40 size_t i;
42 sprintf (buf, fmt, f);
44 // trim off useless zeros and decimals
45 for (i = strlen (buf); i > 0 && buf[i - 1] == '0'; i--)
46 /* skip */ ;
47 if (i > 0 && buf[i - 1] == '.')
48 i--;
49 buf[i] = '\0';
51 // remove leading zeros before decimal
52 if (buf[0] == '0' && buf[1] == '.')
53 for (i = 0; (buf[i] = buf[i + 1]) != '\0'; i++)
54 /* skip */ ;
55 else if (buf[0] == '-' && buf[1] == '0' && buf[2] == '.')
56 for (i = 1; (buf[i] = buf[i + 1]) != '\0'; i++)
57 /* skip */ ;
59 // fix -0
60 if (strcmp (buf, "-0") == 0)
61 strcpy (buf, "0");
63 return buf;
66 char *
67 flt_str (char *buf, double f)
69 return flt_str_fmt ("%.3f", buf, f);
72 // scan and return all the legal forms of special arg: ints, int range,
73 // *arg_len is set to number of chars consumed by scanning even if there are range errors
74 // return value is number of good arg indices scanned into *arg_index_1|2
75 static int
76 scan_special_arg (SPECIAL_OBJECT * special, int i, // start index
77 int *arg_len, // chars scanned
78 int *arg_index_1, // arg array indices (# - 1)
79 int *arg_index_2, SRC_LINE line) // line # for error messages
81 int i1, i2, len, n_args, n_errs;
83 // try two-arg cases and then one arg and then assume zero
84 if (sscanf (&special->code[i], "%d-%d%n", &i1, &i2, &len) >= 2 ||
85 sscanf (&special->code[i], "{%d-%d}%n", &i1, &i2, &len) >= 2)
87 *arg_len = len;
88 *arg_index_1 = i1 - 1;
89 *arg_index_2 = i2 - 1;
90 n_args = 2;
92 else if (sscanf (&special->code[i], "%d%n", &i1, &len) >= 1 ||
93 sscanf (&special->code[i], "{%d}%n", &i1, &len) >= 1)
95 *arg_len = len;
96 *arg_index_1 = i1 - 1;
97 n_args = 1;
99 else
101 *arg_len = 0;
102 n_args = 0;
104 n_errs = 0;
105 if (n_args >= 1 && (i1 < 1 || i1 > special->pts->n_pts))
107 err (line, "special arg #%d: out of range #[1-%d]", i1,
108 special->pts->n_pts);
109 ++n_errs;
111 if (n_args >= 2 && (i2 < 1 || i2 > special->pts->n_pts))
113 err (line, "special arg #n-%d: out of range #[1-%d]", i2,
114 special->pts->n_pts);
115 ++n_errs;
117 return n_errs > 0 ? 0 : n_args;
120 // TikZ only does integer angles
121 char *
122 fmt_angle_tikz (char *buf, double theta, SRC_LINE line)
124 int i_theta = (int) ((theta >= 0) ? (theta + 0.5) : (theta - 0.5));
125 double err = theta - i_theta;
126 if (fabs (err) >= 0.1)
127 warn (line, "TikZ angle rounding error is %.2 degrees", err);
128 return flt_str_fmt ("%1.f", buf, theta);
131 char *
132 fmt_angle_pst (char *buf, double theta, SRC_LINE line)
134 return flt_str (buf, theta);
137 typedef char *(*FMT_ANGLE_FUNC) (char *buf, double theta, SRC_LINE line);
139 FMT_ANGLE_FUNC fmt_angle_tbl[] = {
140 fmt_angle_pst,
141 fmt_angle_tikz,
142 fmt_angle_pst,
143 fmt_angle_tikz,
146 // this parses, substitues, notes any errors, and (if f is set) prints special output
147 // so it's used both for syntax checking during input and to generate output
148 void
149 process_special (FILE * f, SPECIAL_OBJECT * special, SRC_LINE line)
151 char ch, buf1[16], buf2[16];
152 int i_arg_prev, i_arg, arg_len, arg_index_1, arg_index_2;
154 i_arg_prev = i_arg = 0;
155 while ((ch = special->code[i_arg]) != '\0')
157 if (ch == '#')
159 if (special->code[i_arg + 1] == '#')
161 if (f)
162 fprintf (f, "%.*s#",
163 i_arg - i_arg_prev, &special->code[i_arg_prev]);
164 arg_len = 1;
166 else
168 switch (scan_special_arg
169 (special, i_arg + 1, &arg_len, &arg_index_1,
170 &arg_index_2, line))
172 case 2:
173 if (f)
174 fprintf (f, "%.*s{%s}", i_arg - i_arg_prev, // number of chars to write
175 &special->code[i_arg_prev], // start of chars
176 (*fmt_angle_tbl
177 [global_env->output_language])
178 (buf1,
179 180 / PI *
180 atan2 (special->pts->v[arg_index_2][Y] -
181 special->pts->v[arg_index_1][Y],
182 special->pts->v[arg_index_2][X] -
183 special->pts->v[arg_index_1][X]), line));
184 break;
185 case 1:
186 if (f)
187 fprintf (f, "%.*s(%s,%s)", i_arg - i_arg_prev, // number of chars to write
188 &special->code[i_arg_prev], // start of chars
189 flt_str (buf1,
190 special->pts->v[arg_index_1][X]),
191 flt_str (buf2, special->pts->v[arg_index_1][Y]));
192 break;
193 case 0:
194 if (arg_len == 0)
195 { // couldn't scan an index at all
196 if (f)
197 fprintf (f, "%.*s#", i_arg - i_arg_prev,
198 &special->code[i_arg_prev]);
199 warn (line,
200 "use of '#' not as special arg (try ##)",
201 arg_len, &special->code[i_arg]);
203 break;
206 i_arg += (arg_len + 1);
207 i_arg_prev = i_arg;
209 else
211 ++i_arg;
214 // print out the last stretch of code
215 if (f)
216 fprintf (f, "%s\n", &special->code[i_arg_prev]);
219 static void
220 emit_points_pst (FILE * f, POINT_LIST_3D * pts)
222 int i;
223 char buf1[16], buf2[16];
225 for (i = 0; i < pts->n_pts; i++)
226 fprintf (f, "(%s,%s)",
227 flt_str (buf1, pts->v[i][X]), flt_str (buf2, pts->v[i][Y]));
230 static void
231 emit_dots_pst (FILE * f, OBJECT * obj)
233 DOTS_OBJECT *dots = (DOTS_OBJECT *) obj;
234 fprintf (f, "\\psdots");
235 emit_opts (f, dots->opts, global_env->output_language);
236 emit_points_pst (f, dots->pts);
237 fprintf (f, "\n");
240 static void
241 emit_line_pst (FILE * f, OBJECT * obj)
243 LINE_OBJECT *line = (LINE_OBJECT *) obj;
244 fprintf (f, "\\psline");
245 emit_opts (f, line->opts, global_env->output_language);
246 emit_points_pst (f, line->pts);
247 fprintf (f, "\n");
250 static void
251 emit_curve_pst (FILE * f, OBJECT * obj)
253 CURVE_OBJECT *curve = (CURVE_OBJECT *) obj;
254 fprintf (f, "\\pscurve");
255 emit_opts (f, curve->opts, global_env->output_language);
256 emit_points_pst (f, curve->pts);
257 fprintf (f, "\n");
260 static void
261 emit_polygon_pst (FILE * f, OBJECT * obj)
263 POLYGON_OBJECT *poly = (POLYGON_OBJECT *) obj;
264 fprintf (f, "\\pspolygon");
265 emit_opts (f, poly->opts, global_env->output_language);
266 emit_points_pst (f, poly->pts);
267 fprintf (f, "\n");
270 static void
271 emit_special_pst (FILE * f, OBJECT * obj)
273 process_special (f, (SPECIAL_OBJECT *) obj, no_line);
276 typedef void (*EMIT_FUNC) (FILE * f, OBJECT *);
278 static EMIT_FUNC emit_tbl_pst[] = {
279 NULL, // O_BASE
280 NULL, // O_TAG_DEF
281 NULL, // O_OPTS_DEF
282 NULL, // O_SCALAR_DEF
283 NULL, // O_POINT_DEF
284 NULL, // O_VECTOR_DEF
285 NULL, // O_TRANSFORM_DEF
286 emit_dots_pst,
287 emit_line_pst,
288 emit_curve_pst,
289 emit_polygon_pst,
290 emit_special_pst,
291 NULL, // O_SWEEP (flattened)
292 NULL, // O_REPEAT (flattened)
293 NULL, // O_COMPOUND (flattened)
296 static void
297 emit_points_tkz (FILE * f, POINT_LIST_3D * pts, char *twixt, char *final)
299 int i;
300 char buf1[16], buf2[16];
302 for (i = 0; i < pts->n_pts; i++)
303 fprintf (f, "(%s,%s)%s",
304 flt_str (buf1, pts->v[i][X]),
305 flt_str (buf2, pts->v[i][Y]),
306 (i == pts->n_pts - 1) ? final : twixt);
309 static void
310 emit_dots_tkz (FILE * f, OBJECT * obj)
312 static char *skip[] = { "dotsize", NULL };
313 char *dotsize, *cmd;
315 DOTS_OBJECT *dots = (DOTS_OBJECT *) obj;
317 // An ugly hack because TikZ uses special syntax for circles...
318 dotsize = opt_val(dots->opts, "dotsize");
319 if (dotsize == NULL)
320 dotsize = "2pt";
321 cmd = safe_malloc(strlen(dotsize) + 100);
322 sprintf(cmd, " circle (%s)", dotsize);
324 fprintf (f, "\\filldraw");
325 emit_opts_with_exceptions (f, dots->opts, skip, global_env->output_language);
326 emit_points_tkz (f, dots->pts, cmd, cmd);
327 fprintf (f, ";\n");
329 safe_free(cmd);
332 static void
333 emit_line_tkz (FILE * f, OBJECT * obj)
335 LINE_OBJECT *line = (LINE_OBJECT *) obj;
336 fprintf (f, "\\draw");
337 emit_opts (f, line->opts, global_env->output_language);
338 emit_points_tkz (f, line->pts, "--", "");
339 fprintf (f, ";\n");
342 static void
343 emit_curve_tkz (FILE * f, OBJECT * obj)
345 CURVE_OBJECT *curve = (CURVE_OBJECT *) obj;
346 fprintf (f, "\\curve");
347 emit_opts (f, curve->opts, global_env->output_language);
348 emit_points_tkz (f, curve->pts, "--", "");
349 fprintf (f, ";\n");
352 static void
353 emit_polygon_tkz (FILE * f, OBJECT * obj)
355 POLYGON_OBJECT *poly = (POLYGON_OBJECT *) obj;
356 fprintf (f, "\\filldraw");
357 emit_opts (f, poly->opts, global_env->output_language);
358 emit_points_tkz (f, poly->pts, "--", "--cycle");
359 fprintf (f, ";\n");
362 static void
363 emit_special_tkz (FILE * f, OBJECT * obj)
365 process_special (f, (SPECIAL_OBJECT *) obj, no_line);
368 static EMIT_FUNC emit_tbl_tkz[] = {
369 NULL, // O_BASE
370 NULL, // O_TAG_DEF
371 NULL, // O_OPTS_DEF
372 NULL, // O_SCALAR_DEF
373 NULL, // O_POINT_DEF
374 NULL, // O_VECTOR_DEF
375 NULL, // O_TRANSFORM_DEF
376 emit_dots_tkz,
377 emit_line_tkz,
378 emit_curve_tkz,
379 emit_polygon_tkz,
380 emit_special_tkz,
381 NULL, // O_SWEEP (flattened)
382 NULL, // O_REPEAT (flattened)
383 NULL, // O_COMPOUND (flattened)
386 static EMIT_FUNC *emit_tbl_tbl[] = {
387 emit_tbl_pst,
388 emit_tbl_tkz,
389 emit_tbl_pst,
390 emit_tbl_tkz,
393 #define DOC_TEMPLATE_ESCAPE_STRING "%%SKETCH_OUTPUT%%"
394 #define DOC_TEMPLATE_ESCAPE_STRING_LEN (sizeof(DOC_TEMPLATE_ESCAPE_STRING) - 1)
396 char standard_us_doc_template_tikz_latex[] =
397 "\\documentclass[letterpaper,12pt]{article}\n"
398 "\\usepackage[x11names,rgb]{xcolor}\n"
399 "\\usepackage{tikz}\n"
400 "\\usetikzlibrary{snakes}\n"
401 "\\usetikzlibrary{arrows}\n"
402 "\\usetikzlibrary{shapes}\n"
403 "\\usetikzlibrary{backgrounds}\n"
404 "\\usepackage{amsmath}\n"
405 "\\oddsidemargin 0in\n"
406 "\\evensidemargin 0in\n"
407 "\\topmargin 0in\n"
408 "\\headheight 0in\n"
409 "\\headsep 0in\n"
410 "\\textheight 9in\n"
411 "\\textwidth 6.5in\n"
412 "\\begin{document}\n"
413 "\\pagestyle{empty}\n"
414 "\\vspace*{\\fill}\n"
415 "\\begin{center}\n"
416 DOC_TEMPLATE_ESCAPE_STRING "\n"
417 "\\end{center}\n" "\\vspace*{\\fill}\n" "\\end{document}\n";
419 char standard_euro_doc_template_tikz_latex[] =
420 "\\documentclass[a4paper,12pt]{article}\n"
421 "\\usepackage[x11names,rgb]{xcolor}\n"
422 "\\usepackage{tikz}\n"
423 "\\usetikzlibrary{snakes}\n"
424 "\\usetikzlibrary{arrows}\n"
425 "\\usetikzlibrary{shapes}\n"
426 "\\usetikzlibrary{backgrounds}\n"
427 "\\usepackage{amsmath}\n"
428 "\\oddsidemargin -10mm\n"
429 "\\evensidemargin -10mm\n"
430 "\\topmargin 5mm\n"
431 "\\headheight 0cm\n"
432 "\\headsep 0cm\n"
433 "\\textheight 247mm\n"
434 "\\textwidth 160mm\n"
435 "\\begin{document}\n"
436 "\\pagestyle{empty}\n"
437 "\\vspace*{\\fill}\n"
438 "\\begin{center}\n"
439 DOC_TEMPLATE_ESCAPE_STRING "\n"
440 "\\end{center}\n" "\\vspace*{\\fill}\n" "\\end{document}\n";
442 char standard_us_doc_template_pst_latex[] =
443 "\\documentclass[letterpaper,12pt]{article}\n"
444 "\\usepackage{amsmath}\n"
445 "\\usepackage{pstricks}\n"
446 "\\usepackage{pstricks-add}\n"
447 "\\oddsidemargin 0in\n"
448 "\\evensidemargin 0in\n"
449 "\\topmargin 0in\n"
450 "\\headheight 0in\n"
451 "\\headsep 0in\n"
452 "\\textheight 9in\n"
453 "\\textwidth 6.5in\n"
454 "\\begin{document}\n"
455 "\\pagestyle{empty}\n"
456 "\\vspace*{\\fill}\n"
457 "\\begin{center}\n"
458 DOC_TEMPLATE_ESCAPE_STRING "\n"
459 "\\end{center}\n" "\\vspace*{\\fill}\n" "\\end{document}\n";
461 char standard_euro_doc_template_pst_latex[] =
462 "\\documentclass[a4paper,12pt]{article}\n"
463 "\\usepackage{amsmath}\n"
464 "\\usepackage{pstricks}\n"
465 "\\usepackage{pstricks-add}\n"
466 "\\oddsidemargin -10mm\n"
467 "\\evensidemargin -10mm\n"
468 "\\topmargin 5mm\n"
469 "\\headheight 0cm\n"
470 "\\headsep 0cm\n"
471 "\\textheight 247mm\n"
472 "\\textwidth 160mm\n"
473 "\\begin{document}\n"
474 "\\pagestyle{empty}\n"
475 "\\vspace*{\\fill}\n"
476 "\\begin{center}\n"
477 DOC_TEMPLATE_ESCAPE_STRING "\n"
478 "\\end{center}\n" "\\vspace*{\\fill}\n" "\\end{document}\n";
480 /* ---------------------------------------------------------------------- */
482 char standard_us_doc_template_tikz_context[] =
483 "\\usemodule[tikz] \\usetikzlibrary[snakes,arrows,shapes,backgrounds]\n"
484 "\\setuppapersize[letter][letter]\n"
485 "\\setuplayout[topspace=0in,backspace=0in,header=0in,footer=0in,height=middle,width=middle]\n"
486 "\\setuppagenumbering[state=stop] % no page numbers\n"
487 "\\starttext\n"
488 "\\startalignment[middle]\n"
489 DOC_TEMPLATE_ESCAPE_STRING "\n"
490 "\\stopalignment\n"
491 "\\stoptext\n";
493 char standard_euro_doc_template_tikz_context[] =
494 "\\usemodule[tikz] \\usetikzlibrary[snakes,arrows,shapes,backgrounds]\n"
495 "\\setuppapersize[a4][a4]\n"
496 "\\setuplayout[topspace=0cm,backspace=0cm,header=0cm,footer=0cm,height=middle,width=middle]\n"
497 "\\setuppagenumbering[state=stop] % no page numbers\n"
498 "\\starttext\n"
499 "\\startalignment[middle]\n"
500 DOC_TEMPLATE_ESCAPE_STRING "\n"
501 "\\stopalignment\n"
502 "\\stoptext\n";
504 char standard_us_doc_template_pst_context[] =
505 "PSTricks does not work with ConTeXt as of 1 Feb 2008.\n";
507 char standard_euro_doc_template_pst_context[] =
508 "PSTricks does not work with ConTeXt as of 1 Feb 2008.\n";
510 char *standard_us_doc_template[] = {
511 standard_us_doc_template_pst_latex,
512 standard_us_doc_template_tikz_latex,
513 standard_us_doc_template_pst_context,
514 standard_us_doc_template_tikz_context,
517 char *standard_euro_doc_template[] = {
518 standard_euro_doc_template_pst_latex,
519 standard_euro_doc_template_tikz_latex,
520 standard_euro_doc_template_pst_context,
521 standard_euro_doc_template_tikz_context,
524 char *
525 read_file_as_string (FILE * f)
527 size_t len = 0;
528 int buf_size = 1024;
529 char *buf = safe_malloc (buf_size + 1);
530 for (;;)
532 len += fread (buf + len, 1, buf_size - len, f);
533 if (feof (f) || ferror (f))
535 buf[len] = '\0';
536 return buf;
538 buf_size *= 2;
539 buf = safe_realloc (buf, buf_size + 1);
543 char *
544 doc_template_from_file (char *file_name, int output_language)
546 FILE *f;
547 char *r;
549 if (file_name == NULL)
550 return NULL;
551 if (file_name == standard_us_doc_template_file_name_flag)
552 return safe_strdup (standard_us_doc_template[output_language]);
553 if (file_name == standard_euro_doc_template_file_name_flag)
554 return safe_strdup (standard_euro_doc_template[output_language]);
556 f = fopen (file_name, "r");
557 if (!f)
559 err (no_line, "can't open document template '%s%' for input\n",
560 file_name);
561 return safe_strdup (standard_us_doc_template_pst_latex);
563 r = read_file_as_string (f);
564 fclose (f);
565 return r;
568 void
569 emit_preamble_pst_latex (FILE * f, BOX_3D * ext, GLOBAL_ENV * env)
571 char buf1[16], buf2[16], buf3[16], buf4[16];
573 if (global_env_is_set_p (env, GE_OPTS))
575 fprintf (f, "\\psset{");
576 emit_opts_raw (f, env->opts, global_env->output_language);
577 fprintf (f, "}\n");
580 if (global_env_is_set_p (env, GE_FRAME))
582 if (env->frame_opts)
583 fprintf (f, "\\psframebox[%s]{", env->frame_opts);
584 else
585 fprintf (f, "\\psframebox[framesep=0pt]{");
588 fprintf (f, "\\begin{pspicture%s}",
589 global_env_is_set_p (env, GE_EXTENT) ? "*" : "");
591 if (global_env_is_set_p (env, GE_BASELINE))
592 fprintf (f, "[%s]", flt_str (buf1, env->baseline));
594 fprintf (f,
595 "(%s,%s)(%s,%s)\n",
596 flt_str (buf1, ext->min[X]),
597 flt_str (buf2, ext->min[Y]),
598 flt_str (buf3, ext->max[X]), flt_str (buf4, ext->max[Y]));
600 if (cmp_with_global_pst_version(env, STRINGIFY(PST_LINEJOIN_VERSION), no_line) < 0)
602 // old way to set linejoin
603 fprintf (f, "\\pstVerb{1 setlinejoin}\n");
605 else
607 fprintf (f,
608 "%% If your PSTricks is earlier than Version "
609 STRINGIFY(PST_LINEJOIN_VERSION) ", it will fail here.\n"
610 "%% Use sketch -V option for backward compatibility.\n"
611 "\\psset{linejoin=1}\n");
615 void
616 emit_preamble_tkz_latex (FILE * f, BOX_3D * ext, GLOBAL_ENV * env)
618 char buf1[16], buf2[16], buf3[16], buf4[16];
619 int picture_opts_p = 0;
621 if (global_env_is_set_p (env, GE_FRAME))
623 if (env->frame_opts)
624 warn (no_line, "frame options [%s] ignored (TikZ)", env->frame_opts);
625 else
627 fprintf (f, "{\\fboxsep=0pt\\fbox{");
628 warn (no_line,
629 "remove frame around TikZ/PGF pictures for debugging");
633 if (cmp_with_global_tikz_version(env, STRINGIFY(TIKZ_DECORATIONS_VERSION), no_line) >= 0)
635 remark (no_line,
636 "TikZ warning about deprecated decorations library is okay to ignore");
639 fprintf (f, "\\begin{tikzpicture}[line join=round");
640 if (global_env_is_set_p (env, GE_OPTS))
642 fprintf (f, ",");
643 emit_opts_raw (f, env->opts, global_env->output_language);
645 if (global_env_is_set_p (env, GE_BASELINE))
647 fprintf (f, ",");
648 fprintf (f, "baseline=%s", flt_str (buf1, env->baseline));
650 fprintf (f, "]\n");
651 if (global_env_is_set_p (env, GE_EXTENT))
653 flt_str (buf1, ext->min[X]);
654 flt_str (buf2, ext->min[Y]);
655 flt_str (buf3, ext->max[X]);
656 flt_str (buf4, ext->max[Y]);
657 fprintf (f,
658 "\\useasboundingbox(%s,%s) rectangle (%s,%s);\n"
659 "\\clip(%s,%s) rectangle (%s,%s);\n",
660 buf1, buf2, buf3, buf4, buf1, buf2, buf3, buf4);
664 // -----------------------------------------------------------------
666 void
667 emit_preamble_pst_context (FILE * f, BOX_3D * ext, GLOBAL_ENV * env)
669 char buf1[16], buf2[16], buf3[16], buf4[16];
671 if (global_env_is_set_p (env, GE_OPTS))
673 fprintf (f, "\\psset{");
674 emit_opts_raw (f, env->opts, global_env->output_language);
675 fprintf (f, "}\n");
678 fprintf (f,
679 "%% ConTeXt does not yet support PSTricks.\n"
680 "%% This is a guess at what the syntax might be.\n");
682 if (global_env_is_set_p (env, GE_FRAME))
684 if (env->frame_opts)
685 fprintf (f, "\\psframebox[%s]{", env->frame_opts);
686 else
687 fprintf (f, "\\psframebox[framesep=0pt]{");
690 fprintf (f, "\\startpspicture%s",
691 global_env_is_set_p (env, GE_EXTENT) ? "*" : "");
693 if (global_env_is_set_p (env, GE_BASELINE))
694 fprintf (f, "[%s]", flt_str (buf1, env->baseline));
696 fprintf (f,
697 "(%s,%s)(%s,%s)\n",
698 flt_str (buf1, ext->min[X]),
699 flt_str (buf2, ext->min[Y]),
700 flt_str (buf3, ext->max[X]), flt_str (buf4, ext->max[Y]));
702 fprintf (f, "\\pstVerb{1 setlinejoin}\n");
705 void
706 emit_preamble_tkz_context (FILE * f, BOX_3D * ext, GLOBAL_ENV * env)
708 char buf1[16], buf2[16], buf3[16], buf4[16];
709 int picture_opts_p = 0;
711 if (global_env_is_set_p (env, GE_FRAME))
713 if (env->frame_opts)
714 warn (no_line, "frame options [%s] ignored (TikZ)", env->frame_opts);
715 else
717 fprintf (f, "{\\fboxsep=0pt\\fbox{");
718 warn (no_line,
719 "remove frame around TikZ/PGF pictures for debugging");
723 fprintf (f, "\\starttikzpicture[join=round");
724 if (global_env_is_set_p (env, GE_OPTS))
726 fprintf (f, ",");
727 emit_opts_raw (f, env->opts, global_env->output_language);
729 if (global_env_is_set_p (env, GE_BASELINE))
731 fprintf (f, ",");
732 fprintf (f, "baseline=%s", flt_str (buf1, env->baseline));
734 fprintf (f, "]\n");
735 if (global_env_is_set_p (env, GE_EXTENT))
737 flt_str (buf1, ext->min[X]);
738 flt_str (buf2, ext->min[Y]);
739 flt_str (buf3, ext->max[X]);
740 flt_str (buf4, ext->max[Y]);
741 fprintf (f,
742 "\\useasboundingbox(%s,%s) rectangle (%s,%s);\n"
743 "\\clip(%s,%s) rectangle (%s,%s);\n",
744 buf1, buf2, buf3, buf4, buf1, buf2, buf3, buf4);
748 typedef void (*EMIT_PREAMBLE_FUNC) (FILE * f, BOX_3D * ext, GLOBAL_ENV * env);
750 EMIT_PREAMBLE_FUNC emit_preamble_tbl[] = {
751 emit_preamble_pst_latex,
752 emit_preamble_tkz_latex,
753 emit_preamble_pst_context,
754 emit_preamble_tkz_context,
757 void
758 emit_postamble_pst_latex (FILE * f, GLOBAL_ENV * env)
760 fprintf (f, "\\end{pspicture%s}",
761 global_env_is_set_p (env, GE_EXTENT) ? "*" : "");
762 if (global_env_is_set_p (env, GE_FRAME))
763 fprintf (f, "}");
766 void
767 emit_postamble_tkz_latex (FILE * f, GLOBAL_ENV * env)
769 fprintf (f, "\\end{tikzpicture}");
770 if (global_env_is_set_p (env, GE_FRAME))
771 fprintf (f, "}}");
774 void
775 emit_postamble_pst_context (FILE * f, GLOBAL_ENV * env)
777 fprintf (f, "\\stoppspicture%s}",
778 global_env_is_set_p (env, GE_EXTENT) ? "*" : "");
779 if (global_env_is_set_p (env, GE_FRAME))
780 fprintf (f, "}");
783 void
784 emit_postamble_tkz_context (FILE * f, GLOBAL_ENV * env)
786 fprintf (f, "\\stoptikzpicture");
787 if (global_env_is_set_p (env, GE_FRAME))
788 fprintf (f, "}}");
791 typedef void (*EMIT_POSTAMBLE_FUNC) (FILE * f, GLOBAL_ENV * env);
793 EMIT_POSTAMBLE_FUNC emit_postamble_tbl[] = {
794 emit_postamble_pst_latex,
795 emit_postamble_tkz_latex,
796 emit_postamble_pst_context,
797 emit_postamble_tkz_context,
800 void
801 emit (FILE * f, OBJECT * obj, GLOBAL_ENV * env, char *doc_template_file_name)
803 BOX_3D ext[1];
804 int n_obj;
805 OBJECT *p;
806 char buf1[16], buf2[16], buf3[16], buf4[16];
807 char *escape, *doc_template;
809 doc_template =
810 doc_template_from_file (doc_template_file_name, env->output_language);
812 get_extent (obj, ext, &n_obj);
813 if (n_obj == 0)
814 err (no_line, "no objects to write");
815 else
818 remark (no_line, "scene bb=(%s,%s)(%s,%s)",
819 flt_str (buf1, ext->min[X]),
820 flt_str (buf2, ext->min[Y]),
821 flt_str (buf3, ext->max[X]), flt_str (buf4, ext->max[Y]));
823 if (get_transformed_global_env_extent (ext, env))
825 remark (no_line, "actual bb=(%s,%s)(%s,%s)",
826 flt_str (buf1, ext->min[X]),
827 flt_str (buf2, ext->min[Y]),
828 flt_str (buf3, ext->max[X]), flt_str (buf4, ext->max[Y]));
831 remark (no_line, "writing %d objects", n_obj);
833 fprintf (f,
834 "%% Sketch output, version " VER_STRING "\n"
835 "%% Output language: %s\n",
836 output_language_str[env->output_language]);
837 escape = NULL;
838 if (doc_template)
840 escape = strstr (doc_template, DOC_TEMPLATE_ESCAPE_STRING);
841 if (escape)
842 fprintf (f, "%.*s", escape - doc_template, doc_template);
843 else
844 warn (no_line,
845 "document template with no escape '%s' has been ignored",
846 DOC_TEMPLATE_ESCAPE_STRING);
849 (*emit_preamble_tbl[env->output_language]) (f, ext, env);
851 for (p = obj; p; p = p->sibling)
853 if (emit_tbl_tbl[global_env->output_language][p->tag] == NULL)
854 die (no_line, "emit: bad tag %d", p->tag);
855 if (xy_overlap_p (p, ext))
856 (*emit_tbl_tbl[global_env->output_language][p->tag]) (f, p);
859 (*emit_postamble_tbl[env->output_language]) (f, env);
861 if (escape)
863 escape += DOC_TEMPLATE_ESCAPE_STRING_LEN;
864 fprintf (f, "%s", escape);
865 if (strstr (escape, DOC_TEMPLATE_ESCAPE_STRING))
866 warn (no_line,
867 "more than one escape in document template; all but first ignored");
869 fprintf (f, "%% End sketch output\n");