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)
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 */
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
38 flt_str_fmt (char *fmt
, char *buf
, double f
)
42 sprintf (buf
, fmt
, f
);
44 // trim off useless zeros and decimals
45 for (i
= strlen (buf
); i
> 0 && buf
[i
- 1] == '0'; i
--)
47 if (i
> 0 && buf
[i
- 1] == '.')
51 // remove leading zeros before decimal
52 if (buf
[0] == '0' && buf
[1] == '.')
53 for (i
= 0; (buf
[i
] = buf
[i
+ 1]) != '\0'; i
++)
55 else if (buf
[0] == '-' && buf
[1] == '0' && buf
[2] == '.')
56 for (i
= 1; (buf
[i
] = buf
[i
+ 1]) != '\0'; i
++)
60 if (strcmp (buf
, "-0") == 0)
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
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)
88 *arg_index_1
= i1
- 1;
89 *arg_index_2
= i2
- 1;
92 else if (sscanf (&special
->code
[i
], "%d%n", &i1
, &len
) >= 1 ||
93 sscanf (&special
->code
[i
], "{%d}%n", &i1
, &len
) >= 1)
96 *arg_index_1
= i1
- 1;
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
);
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
);
117 return n_errs
> 0 ? 0 : n_args
;
120 // TikZ only does integer angles
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
);
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
[] = {
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
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')
159 if (special
->code
[i_arg
+ 1] == '#')
163 i_arg
- i_arg_prev
, &special
->code
[i_arg_prev
]);
168 switch (scan_special_arg
169 (special
, i_arg
+ 1, &arg_len
, &arg_index_1
,
174 fprintf (f
, "%.*s{%s}", i_arg
- i_arg_prev
, // number of chars to write
175 &special
->code
[i_arg_prev
], // start of chars
177 [global_env
->output_language
])
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
));
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
190 special
->pts
->v
[arg_index_1
][X
]),
191 flt_str (buf2
, special
->pts
->v
[arg_index_1
][Y
]));
195 { // couldn't scan an index at all
197 fprintf (f
, "%.*s#", i_arg
- i_arg_prev
,
198 &special
->code
[i_arg_prev
]);
200 "use of '#' not as special arg (try ##)",
201 arg_len
, &special
->code
[i_arg
]);
206 i_arg
+= (arg_len
+ 1);
214 // print out the last stretch of code
216 fprintf (f
, "%s\n", &special
->code
[i_arg_prev
]);
220 emit_points_pst (FILE * f
, POINT_LIST_3D
* pts
)
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
]));
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
);
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
);
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
);
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
);
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
[] = {
282 NULL
, // O_SCALAR_DEF
284 NULL
, // O_VECTOR_DEF
285 NULL
, // O_TRANSFORM_DEF
291 NULL
, // O_SWEEP (flattened)
292 NULL
, // O_REPEAT (flattened)
293 NULL
, // O_COMPOUND (flattened)
297 emit_points_tkz (FILE * f
, POINT_LIST_3D
* pts
, char *twixt
, char *final
)
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
);
310 emit_dots_tkz (FILE * f
, OBJECT
* obj
)
312 static char *skip
[] = { "dotsize", NULL
};
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");
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
);
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
, "--", "");
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
, "--", "");
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");
363 emit_special_tkz (FILE * f
, OBJECT
* obj
)
365 process_special (f
, (SPECIAL_OBJECT
*) obj
, no_line
);
368 static EMIT_FUNC emit_tbl_tkz
[] = {
372 NULL
, // O_SCALAR_DEF
374 NULL
, // O_VECTOR_DEF
375 NULL
, // O_TRANSFORM_DEF
381 NULL
, // O_SWEEP (flattened)
382 NULL
, // O_REPEAT (flattened)
383 NULL
, // O_COMPOUND (flattened)
386 static EMIT_FUNC
*emit_tbl_tbl
[] = {
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"
411 "\\textwidth 6.5in\n"
412 "\\begin{document}\n"
413 "\\pagestyle{empty}\n"
414 "\\vspace*{\\fill}\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"
433 "\\textheight 247mm\n"
434 "\\textwidth 160mm\n"
435 "\\begin{document}\n"
436 "\\pagestyle{empty}\n"
437 "\\vspace*{\\fill}\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"
453 "\\textwidth 6.5in\n"
454 "\\begin{document}\n"
455 "\\pagestyle{empty}\n"
456 "\\vspace*{\\fill}\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"
471 "\\textheight 247mm\n"
472 "\\textwidth 160mm\n"
473 "\\begin{document}\n"
474 "\\pagestyle{empty}\n"
475 "\\vspace*{\\fill}\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"
488 "\\startalignment[middle]\n"
489 DOC_TEMPLATE_ESCAPE_STRING
"\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"
499 "\\startalignment[middle]\n"
500 DOC_TEMPLATE_ESCAPE_STRING
"\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
,
525 read_file_as_string (FILE * f
)
529 char *buf
= safe_malloc (buf_size
+ 1);
532 len
+= fread (buf
+ len
, 1, buf_size
- len
, f
);
533 if (feof (f
) || ferror (f
))
539 buf
= safe_realloc (buf
, buf_size
+ 1);
544 doc_template_from_file (char *file_name
, int output_language
)
549 if (file_name
== 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");
559 err (no_line
, "can't open document template '%s%' for input\n",
561 return safe_strdup (standard_us_doc_template_pst_latex
);
563 r
= read_file_as_string (f
);
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
);
580 if (global_env_is_set_p (env
, GE_FRAME
))
583 fprintf (f
, "\\psframebox[%s]{", env
->frame_opts
);
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
));
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");
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");
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
))
624 warn (no_line
, "frame options [%s] ignored (TikZ)", env
->frame_opts
);
627 fprintf (f
, "{\\fboxsep=0pt\\fbox{");
629 "remove frame around TikZ/PGF pictures for debugging");
633 if (cmp_with_global_tikz_version(env
, STRINGIFY(TIKZ_DECORATIONS_VERSION
), no_line
) >= 0)
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
))
643 emit_opts_raw (f
, env
->opts
, global_env
->output_language
);
645 if (global_env_is_set_p (env
, GE_BASELINE
))
648 fprintf (f
, "baseline=%s", flt_str (buf1
, env
->baseline
));
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
]);
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 // -----------------------------------------------------------------
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
);
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
))
685 fprintf (f
, "\\psframebox[%s]{", env
->frame_opts
);
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
));
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");
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
))
714 warn (no_line
, "frame options [%s] ignored (TikZ)", env
->frame_opts
);
717 fprintf (f
, "{\\fboxsep=0pt\\fbox{");
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
))
727 emit_opts_raw (f
, env
->opts
, global_env
->output_language
);
729 if (global_env_is_set_p (env
, GE_BASELINE
))
732 fprintf (f
, "baseline=%s", flt_str (buf1
, env
->baseline
));
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
]);
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
,
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
))
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
))
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
))
784 emit_postamble_tkz_context (FILE * f
, GLOBAL_ENV
* env
)
786 fprintf (f
, "\\stoptikzpicture");
787 if (global_env_is_set_p (env
, GE_FRAME
))
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
,
801 emit (FILE * f
, OBJECT
* obj
, GLOBAL_ENV
* env
, char *doc_template_file_name
)
806 char buf1
[16], buf2
[16], buf3
[16], buf4
[16];
807 char *escape
, *doc_template
;
810 doc_template_from_file (doc_template_file_name
, env
->output_language
);
812 get_extent (obj
, ext
, &n_obj
);
814 err (no_line
, "no objects to write");
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
);
834 "%% Sketch output, version " VER_STRING
"\n"
835 "%% Output language: %s\n",
836 output_language_str
[env
->output_language
]);
840 escape
= strstr (doc_template
, DOC_TEMPLATE_ESCAPE_STRING
);
842 fprintf (f
, "%.*s", escape
- doc_template
, doc_template
);
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
);
863 escape
+= DOC_TEMPLATE_ESCAPE_STRING_LEN
;
864 fprintf (f
, "%s", escape
);
865 if (strstr (escape
, DOC_TEMPLATE_ESCAPE_STRING
))
867 "more than one escape in document template; all but first ignored");
869 fprintf (f
, "%% End sketch output\n");