1 /* output-epd.c: utility routines for EPD output
2 (http://epd.sourceforge.net)
3
4 Copyright (C) 1999, 2000, 2001 Martin Weber.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public License
8 as published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA. */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* Def: HAVE_CONFIG_H */
24
25 #include "types.h"
26 #include "spline.h"
27 #include "color.h"
28 #include "output-epd.h"
29 #include "xstd.h"
30 #include "autotrace.h"
31 #include <time.h>
32 #include <string.h>
33
34 static at_string now (void);
35
36 #define SIGN(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0)
37 #define ROUND(x) ((int) ((int) (x) + .5 * SIGN (x)))
38
39 /* Output macros. */
40
41 /* This should be used for outputting a string S on a line by itself. */
42 #define OUT_LINE(s) \
43 fprintf (epd_file, "%s\n", s)
44
45 /* These output their arguments, preceded by the indentation. */
46 #define OUT1(s, e) \
47 fprintf (epd_file, s, e)
48
49 #define OUT2(s, e1, e2) \
50 fprintf (epd_file, s, e1, e2)
51
52 #define OUT3(s, e1, e2, e3) \
53 fprintf (epd_file, s, e1, e2, e3)
54
55 #define OUT4(s, e1, e2, e3, e4) \
56 fprintf (epd_file, s, e1, e2, e3, e4)
57
58 /* These macros just output their arguments. */
59 #define OUT_STRING(s) fprintf (epd_file, "%s", s)
60 #define OUT_REAL(r) fprintf (epd_file, r == (ROUND (r = ROUND((at_real)6.0*r)/(at_real)6.0)) \
61 ? "%.0f " : "%.3f ", r)
62
63 /* For a PostScript command with two real arguments, e.g., lineto. OP
64 should be a constant string. */
65 #define OUT_COMMAND2(first, second, op) \
66 do \
67 { \
68 OUT_REAL (first); \
69 OUT_REAL (second); \
70 OUT_STRING (op "\n"); \
71 } \
72 while (0)
73
74 /* For a PostScript command with six real arguments, e.g., curveto.
75 Again, OP should be a constant string. */
76 #define OUT_COMMAND6(first, second, third, fourth, fifth, sixth, op) \
77 do \
78 { \
79 OUT_REAL (first); \
80 OUT_REAL (second); \
81 OUT_STRING (" "); \
82 OUT_REAL (third); \
83 OUT_REAL (fourth); \
84 OUT_STRING (" "); \
85 OUT_REAL (fifth); \
86 OUT_REAL (sixth); \
87 OUT_STRING (" " op " \n"); \
88 } \
89 while (0)
90
91 /* This should be called before the others in this file. It opens the
92 output file `OUTPUT_NAME.ps', and writes some preliminary boilerplate. */
93
output_epd_header(FILE * epd_file,at_string name,int llx,int lly,int urx,int ury)94 static int output_epd_header(FILE* epd_file, at_string name,
95 int llx, int lly, int urx, int ury)
96 {
97 at_string time;
98
99 OUT_LINE ("%EPD-1.0");
100 OUT1 ("%% Created by %s\n", at_version(true));
101 OUT1 ("%% Title: %s\n", name);
102 OUT1 ("%% CreationDate: %s\n", time = now ());
103 OUT4 ("%%BBox(%d,%d,%d,%d)\n", llx, lly, urx, ury);
104
105 free (time);
106
107 return 0;
108 }
109
110 /* This outputs the PostScript code which produces the shape in
111 SHAPE. */
112
113 static void
out_splines(FILE * epd_file,spline_list_array_type shape)114 out_splines (FILE * epd_file, spline_list_array_type shape)
115 {
116 unsigned this_list;
117 spline_list_type list;
118 color_type last_color = {0,0,0};
119
120 for (this_list = 0; this_list < SPLINE_LIST_ARRAY_LENGTH (shape);
121 this_list++)
122 {
123 unsigned this_spline;
124 spline_type first;
125
126 list = SPLINE_LIST_ARRAY_ELT (shape, this_list);
127 first = SPLINE_LIST_ELT (list, 0);
128
129 if (this_list == 0 || !COLOR_EQUAL(list.color, last_color))
130 {
131 if (this_list > 0)
132 {
133 OUT_LINE ((shape.centerline || list.open) ? "S" : "f");
134 OUT_LINE("h");
135 }
136 OUT4 ("%.3f %.3f %.3f %s\n", (double) list.color.r / 255.0,
137 (double) list.color.g / 255.0, (double) list.color.b / 255.0,
138 (shape.centerline || list.open) ? "RG" : "rg");
139 last_color = list.color;
140 }
141 OUT_COMMAND2 (START_POINT (first).x, START_POINT (first).y, "m");
142
143 for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH (list);
144 this_spline++)
145 {
146 spline_type s = SPLINE_LIST_ELT (list, this_spline);
147
148 if (SPLINE_DEGREE (s) == LINEARTYPE)
149 OUT_COMMAND2 (END_POINT (s).x, END_POINT (s).y, "l");
150 else
151 OUT_COMMAND6 (CONTROL1 (s).x, CONTROL1 (s).y,
152 CONTROL2 (s).x, CONTROL2 (s).y,
153 END_POINT (s).x, END_POINT (s).y,
154 "c");
155 }
156 }
157 if (SPLINE_LIST_ARRAY_LENGTH(shape) > 0)
158 OUT_LINE ((shape.centerline || list.open) ? "S" : "f");
159 }
160
161
output_epd_writer(FILE * epd_file,at_string name,int llx,int lly,int urx,int ury,at_output_opts_type * opts,spline_list_array_type shape,at_msg_func msg_func,at_address msg_data)162 int output_epd_writer(FILE* epd_file, at_string name,
163 int llx, int lly, int urx, int ury,
164 at_output_opts_type * opts,
165 spline_list_array_type shape,
166 at_msg_func msg_func,
167 at_address msg_data)
168 {
169 int result;
170
171 result = output_epd_header(epd_file, name, llx, lly, urx, ury);
172 if (result != 0)
173 return result;
174
175 out_splines(epd_file, shape);
176
177 return 0;
178 }
179
180
181 static at_string
now(void)182 now (void)
183 {
184 at_string time_string;
185 time_t t = time (0);
186
187 XMALLOC (time_string, 26); /* not 25 ! */
188 strcpy (time_string, ctime (&t));
189 time_string[24] = 0; /* No newline. */
190
191 return time_string;
192 }
193