1 /*
2 * $Id: postscript.c,v 1.20 2001/02/13 23:38:06 danny Exp $
3 *
4 * This file is part of Oleo, the GNU spreadsheet.
5 *
6 * Copyright � 1999, 2000, 2001 by the Free Software Foundation, Inc.
7 * Written by Danny Backx <danny@gnu.org>.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /*
25 * This file contains the PostScript specific printing support.
26 * It is called by src/print.c which contains general printing support.
27 *
28 * There shouldn't be much spreadsheet functionality here...
29 */
30
31 static char rcsid[] = "$Id: postscript.c,v 1.20 2001/02/13 23:38:06 danny Exp $";
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #ifdef WITH_DMALLOC
38 #include <dmalloc.h>
39 #endif
40
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <locale.h>
44
45 #include "display.h"
46 #include "font.h"
47 #include "global.h"
48 #include "cmd.h"
49 #include "io-generic.h"
50 #include "io-abstract.h"
51 #include "print.h"
52
53 /*
54 * FIX ME these should be static
55 */
56 extern float default_pswid, default_pshgt;
57
58 static int CurrentFontSize = 0;
59 static char *ps_encoding = NULL;
60
61 void
put_ps_string(char * str,FILE * fp)62 put_ps_string (char *str, FILE *fp)
63 {
64 fputc ('(', fp);
65 while (*str)
66 {
67 if (*str == ')')
68 fputs ("\\)", fp);
69 else if (*str == '(')
70 fputs ("\\(", fp);
71 else
72 fputc (*str, fp);
73 ++str;
74 }
75 fputc (')', fp);
76 }
77
78 static char **KnownFonts = NULL;
79 static int nfonts = 0;
80
FontCacheRestart(void)81 void FontCacheRestart(void)
82 {
83 free(KnownFonts);
84 KnownFonts = 0;
85 nfonts = 0;
86 }
87
ReencodeFont(char * fn,FILE * fp)88 void ReencodeFont(char *fn, FILE *fp)
89 {
90 int i;
91
92 for (i=0; i<nfonts; i++)
93 if (strcmp(fn, KnownFonts[i]) == 0)
94 return;
95
96 nfonts++;
97 KnownFonts = realloc(KnownFonts, sizeof(char *) * nfonts);
98
99 KnownFonts[nfonts-1] = strdup(fn);
100
101 fprintf(fp, "/%sISO /%s reencodeISO\n", fn, fn);
102 }
103
PostScriptEncoding(char * encoding)104 void PostScriptEncoding(char *encoding)
105 {
106 if (ps_encoding)
107 free(ps_encoding);
108 ps_encoding = strdup(encoding);
109 }
110
PostScriptJobHeader(char * title,int npages,FILE * fp)111 void PostScriptJobHeader(char *title, int npages, FILE *fp)
112 {
113 struct font_names *fn;
114 struct font_memo *fm;
115
116 if (! Global->oldLocale)
117 Global->oldLocale = setlocale(LC_ALL, NULL);
118
119 FontCacheRestart();
120
121 fprintf(fp, "%%!PS-Adobe-3.0\n");
122 fprintf(fp, "%%%%Creator: %s %s\n", PACKAGE, VERSION);
123 fprintf(fp, "%%%%Pages: (atend)\n");
124 fprintf(fp, "%%%%PageOrder: Ascend\n");
125
126 /*
127 * Print a list of all fonts
128 */
129 fprintf(fp, "%%%%DocumentFonts:");
130 for (fm = font_list; fm; fm = fm->next) {
131 if ((fn = fm->names) == 0)
132 continue;
133 if (fn->ps_name == 0 || strlen(fn->ps_name) == 0)
134 continue;
135 fprintf(fp, " %sISO", fn->ps_name);
136 }
137 fprintf(fp, "\n");
138
139 /* done */
140
141 fprintf(fp, "%%%%Title: %s\n", title);
142 fprintf(fp, "%%%%EndComments\n%%%%BeginProlog\n");
143
144 /*
145 * Define a function to reencode all fonts to ISO Latin 1
146 * (or another known encoding).
147 */
148 fprintf(fp, "/reencodeISO { %%def\n");
149 fprintf(fp, " findfont dup length dict begin\n");
150 fprintf(fp, " { 1 index /FID ne { def }{ pop pop } ifelse } forall\n");
151 fprintf(fp, " /Encoding %sEncoding def\n",
152 ps_encoding ? ps_encoding : "ISOLatin1");
153 fprintf(fp, " currentdict end definefont pop\n");
154 fprintf(fp, "} bind def\n");
155
156 /*
157 * Remap all used fonts to ISO, give them a new name.
158 */
159 for (fm = font_list; fm; fm = fm->next) {
160 if ((fn = fm->names) == 0)
161 continue;
162 if (fn->ps_name == 0 || strlen(fn->ps_name) == 0)
163 continue;
164 ReencodeFont(fn->ps_name, fp);
165 }
166
167 /* Don't forget Courier */
168 ReencodeFont("Courier", fp);
169
170 /*
171 *
172 */
173 fprintf(fp, "/FontName where { pop } { /FontName (Courier) def } ifelse\n");
174 fprintf(fp, "/FirstSize where { pop } { /FirstSize 10 def } ifelse\n");
175 fprintf(fp, "%%%%EndProlog\n");
176
177 }
178
PostScriptJobTrailer(int npages,FILE * fp)179 void PostScriptJobTrailer(int npages, FILE *fp)
180 {
181 fprintf(fp, "%%Pages: %d\n", npages);
182 fprintf(fp, "%%EOF\n");
183
184 setlocale(LC_ALL, Global->oldLocale);
185 }
186
187 /*
188 * These variables hold the position we're printing at
189 */
190 static float x, y;
191 static float paper_width, paper_height;
192 static float border_width = 20.0,
193 border_height = 20.0;
194
195 /*
196 * MULTIPLY_WIDTH should provide the mapping between string length (in chars)
197 * and visible length in points.
198 */
199 /*
200 * 8 : too wide
201 * 6 : no margin between columns
202 * 7 : ??
203 */
204 #define MULTIPLY_WIDTH 12
205
PostScriptPageHeader(char * str,FILE * fp)206 void PostScriptPageHeader(char *str, FILE *fp)
207 {
208 fprintf(fp, "%%%%Page: %s\n", str);
209
210 x = border_width;
211 y = paper_height - border_height;
212 }
213
PostScriptPageFooter(char * str,FILE * fp)214 void PostScriptPageFooter(char *str, FILE *fp)
215 {
216 fprintf(fp, "showpage\n");
217 }
218
PostScriptField(char * str,int wid,int rightborder,int xpoints,int xchars,FILE * fp)219 void PostScriptField(char *str, int wid, int rightborder,
220 int xpoints, int xchars, FILE *fp)
221 {
222 #if 0
223 fprintf(stderr, "PostScriptField(%s, wid %d, xpoints %d)\n",
224 str, wid, xpoints);
225 #endif
226 if (strlen(str)) {
227 fprintf(fp, "%3.1f %3.1f moveto ", border_width + xpoints, y);
228
229 put_ps_string(str, fp);
230 fprintf(fp, " show\n");
231 }
232
233 x += wid;
234
235 if (rightborder) {
236 }
237 }
238
PostScriptBorders(FILE * fp)239 void PostScriptBorders(FILE *fp)
240 {
241 }
242
changed(char * a,char * b)243 static int changed(char *a, char *b)
244 {
245 if (a == 0 && b == 0)
246 return 0;
247 if (a == 0 || b == 0)
248 return 1;
249 return strcmp(a, b);
250 }
251
PostScriptFont(char * family,char * slant,int size,FILE * fp)252 void PostScriptFont(char *family, char *slant, int size, FILE *fp)
253 {
254 static char *of = NULL, *osl = NULL;
255 static int osz = 0;
256
257 if ((! changed(family, of)) && (! changed(slant, osl)) && size == osz)
258 return;
259
260 fprintf(fp, "/%sISO findfont %d scalefont setfont\n", family, size);
261
262 CurrentFontSize = size;
263
264 if (of) free(of);
265 if (osl) free(osl);
266
267 osl = of = NULL;
268
269 if (family) of = strdup(family);
270 if (slant) osl = strdup(slant);
271 osz = size;
272 }
273
PostScriptNewLine(int ht,FILE * fp)274 void PostScriptNewLine(int ht, FILE *fp)
275 {
276 x = border_width;
277 y -= ht;
278 }
279
PostScriptPaperSize(int wid,int ht,FILE * fp)280 void PostScriptPaperSize(int wid, int ht, FILE *fp)
281 {
282 paper_width = wid;
283 paper_height = ht;
284 }
285
PostScriptSetBorder(int width,int height,FILE * fp)286 void PostScriptSetBorder(int width, int height, FILE *fp)
287 {
288 border_width = width;
289 border_height = height;
290 }
291
292 struct PrintDriver PostScriptPrintDriver = {
293 "PostScript",
294 &PostScriptJobHeader,
295 &PostScriptJobTrailer,
296 &PostScriptPageHeader,
297 &PostScriptPageFooter,
298 &PostScriptField,
299 &PostScriptBorders,
300 &PostScriptFont,
301 &PostScriptNewLine,
302 &PostScriptPaperSize,
303 &PostScriptEncoding,
304 &PostScriptSetBorder
305 };
306