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