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