1 /*
2  * tkImgPS.c --
3  *
4  * A photo image file handler for postscript files.
5  *
6  */
7 
8 /* Author : Jan Nijtmans */
9 /* Date   : 7/24/97        */
10 
11 #include <string.h>
12 #include <stdlib.h>
13 
14 #include "imgInt.h"
15 
16 /*
17  * The format record for the PS file format:
18  */
19 
20 static int ChanMatchPS _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Channel chan,
21 	CONST char *fileName, Tcl_Obj *format, int *widthPtr, int *heightPtr));
22 static int ObjMatchPS _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj,
23 	Tcl_Obj *format, int *widthPtr, int *heightPtr));
24 static int ChanMatchPDF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Channel chan,
25 	CONST char *fileName, Tcl_Obj *format, int *widthPtr, int *heightPtr));
26 static int ObjMatchPDF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj,
27 	Tcl_Obj *format, int *widthPtr, int *heightPtr));
28 static int ChanReadPS _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Channel chan,
29 	CONST char *fileName, Tcl_Obj *format, Tk_PhotoHandle imageHandle,
30 	int destX, int destY, int width, int height, int srcX, int srcY));
31 static int ObjReadPS _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj,
32 	Tcl_Obj *format, Tk_PhotoHandle imageHandle,
33 	int destX, int destY, int width, int height, int srcX, int srcY));
34 static int ChanReadPDF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Channel chan,
35 	CONST char *fileName, Tcl_Obj *format, Tk_PhotoHandle imageHandle,
36 	int destX, int destY, int width, int height, int srcX, int srcY));
37 static int ObjReadPDF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj,
38 	Tcl_Obj *format, Tk_PhotoHandle imageHandle,
39 	int destX, int destY, int width, int height, int srcX, int srcY));
40 static int ChanWritePS _ANSI_ARGS_((Tcl_Interp *interp, CONST char *filename,
41 	Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr));
42 static int StringWritePS _ANSI_ARGS_((Tcl_Interp *interp,
43 	Tcl_DString *dataPtr, Tcl_Obj *format,
44 	Tk_PhotoImageBlock *blockPtr));
45 
46 Tk_PhotoImageFormat imgFmtPS = {
47     "postscript",				/* name */
48     (Tk_ImageFileMatchProc *) ChanMatchPS,	/* fileMatchProc */
49     (Tk_ImageStringMatchProc *) ObjMatchPS,	/* stringMatchProc */
50     (Tk_ImageFileReadProc *) ChanReadPS,	/* fileReadProc */
51     (Tk_ImageStringReadProc *) ObjReadPS,	/* stringReadProc */
52     (Tk_ImageFileWriteProc *) ChanWritePS,	/* fileWriteProc */
53     (Tk_ImageStringWriteProc *) StringWritePS,	/* stringWriteProc */
54 };
55 
56 Tk_PhotoImageFormat imgFmtPDF = {
57     "pdf",					/* name */
58     (Tk_ImageFileMatchProc *) ChanMatchPDF,	/* fileMatchProc */
59     (Tk_ImageStringMatchProc *) ObjMatchPDF,	/* stringMatchProc */
60     (Tk_ImageFileReadProc *) ChanReadPDF,	/* fileReadProc */
61     (Tk_ImageStringReadProc *) ObjReadPDF,	/* stringReadProc */
62     (Tk_ImageFileWriteProc *) ChanWritePS,	/* fileWriteProc */
63     (Tk_ImageStringWriteProc *) StringWritePS,	/* stringWriteProc */
64 };
65 
66 /*
67  * Prototypes for local procedures defined in this file:
68  */
69 
70 static int CommonMatchPS _ANSI_ARGS_((MFile *handle, Tcl_Obj *format,
71 	int *widthPtr, int *heightPtr));
72 static int CommonMatchPDF _ANSI_ARGS_((MFile *handle, Tcl_Obj *format,
73 	int *widthPtr, int *heightPtr));
74 static int CommonReadPS _ANSI_ARGS_((Tcl_Interp *interp, MFile *handle,
75 	Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY,
76 	int width, int height, int srcX, int srcY));
77 static int CommonWritePS _ANSI_ARGS_((Tcl_Interp *interp, MFile *handle,
78 	Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr));
79 static int parseFormat _ANSI_ARGS_((Tcl_Obj *format, int *zoomx,
80 	int *zoomy));
81 
parseFormat(format,zoomx,zoomy)82 static int parseFormat(format, zoomx, zoomy)
83      Tcl_Obj *format;
84      int *zoomx;
85      int *zoomy;
86 {
87     int objc, i, length, index = 0;
88     Tcl_Obj **objv = NULL;
89     char *p;
90     double zx = 1.0, zy = 1.0;
91 
92     if (!format) {
93 	*zoomx = (int) (72 * zx + 0.5);
94 	*zoomy = (int) (72 * zy + 0.5);
95     }
96 
97     if (ImgListObjGetElements((Tcl_Interp*) NULL, format, &objc, &objv) != TCL_OK) {
98 	return -1;
99     }
100     for (i=1; i<objc; i++) {
101 	p = Tcl_GetStringFromObj(objv[i], &length);
102 	if ((p[0] == '-') && ((i+1)<objc)) {
103 	    if (length < 2) {
104 		index = -1; break;
105 	    }
106 	    if (!strncmp(p,"-index", length)) {
107 		if (Tcl_GetIntFromObj((Tcl_Interp *) NULL, objv[++i], &index) != TCL_OK) {
108 		    index = -1; break;
109 		}
110 	    } else if (!strncmp(p, "-zoom", length)) {
111 		if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objv[++i], &zx) != TCL_OK) {
112 		    index = -1; break;
113 		}
114 		if (i > objc) {
115 		    zy = zx;
116 		} else {
117 		    p = Tcl_GetStringFromObj(objv[i+1], &length);
118 		    if (p[0] != '-') {
119 			if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objv[++i], &zy) != TCL_OK) {
120 			    index = -1; break;
121 			}
122 		    } else {
123 			zy = zx;
124 		    }
125 		}
126 	    } else {
127 		index = -1; break;
128 	    }
129 	} else {
130 	    if (Tcl_GetIntFromObj((Tcl_Interp *) NULL, objv[++i], &index) != TCL_OK) {
131 		index = -1; break;
132 	    }
133 	}
134     }
135     if (!index) {
136 	*zoomx = (int) (72 * zx + 0.5);
137 	*zoomy = (int) (72 * zy + 0.5);
138     }
139     return index;
140 }
141 
ChanMatchPS(interp,chan,fileName,format,widthPtr,heightPtr)142 static int ChanMatchPS(interp, chan, fileName, format, widthPtr, heightPtr)
143     Tcl_Interp *interp;
144     Tcl_Channel chan;
145     CONST char *fileName;
146     Tcl_Obj *format;
147     int *widthPtr, *heightPtr;
148 {
149     MFile handle;
150 
151     ImgFixChanMatchProc(&interp, &chan, &fileName, &format, &widthPtr, &heightPtr);
152 
153     handle.data = (char *) chan;
154     handle.state = IMG_CHAN;
155 
156     return CommonMatchPS(&handle, format, widthPtr, heightPtr);
157 }
158 
ObjMatchPS(interp,data,format,widthPtr,heightPtr)159 static int ObjMatchPS(interp, data, format, widthPtr, heightPtr)
160     Tcl_Interp *interp;
161     Tcl_Obj *data;
162     Tcl_Obj *format;
163     int *widthPtr, *heightPtr;
164 {
165     MFile handle;
166 
167     ImgFixObjMatchProc(&interp, &data, &format, &widthPtr, &heightPtr);
168 
169     handle.data = ImgGetStringFromObj(data, &handle.length);
170     handle.state = IMG_STRING;
171 
172     return CommonMatchPS(&handle, format, widthPtr, heightPtr);
173 }
174 
CommonMatchPS(handle,format,widthPtr,heightPtr)175 static int CommonMatchPS(handle, format, widthPtr, heightPtr)
176     MFile *handle;
177     Tcl_Obj *format;
178     int *widthPtr, *heightPtr;
179 {
180     unsigned char buf[41];
181 
182     if ((ImgRead(handle, (char *) buf, 11) != 11)
183 	    || (strncmp("%!PS-Adobe-", (char *) buf, 11) != 0)) {
184 	return 0;
185     }
186     while (ImgRead(handle,(char *) buf, 1) == 1) {
187 	if (buf[0] == '%' &&
188 		(ImgRead(handle, (char *) buf, 2) == 2) &&
189 		(!memcmp(buf, "%B", 2) &&
190 		(ImgRead(handle, (char *) buf, 11) == 11) &&
191 		(!memcmp(buf, "oundingBox:", 11)) &&
192 		(ImgRead(handle, (char *) buf, 40) == 40))) {
193 	    int w, h, zoomx, zoomy;
194 	    char *p = buf;
195 	    buf[41] = 0;
196 	    w = - (int) strtoul(p, &p, 0);
197 	    h = - (int) strtoul(p, &p, 0);
198 	    w += strtoul(p, &p, 0);
199 	    h += strtoul(p, &p, 0);
200 	    if (parseFormat(format, &zoomx, &zoomy) >= 0) {
201 		w = (w * zoomx + 36) / 72;
202 		h = (h * zoomy + 36) / 72;
203 	    }
204 	    if ((w <= 0) || (h <= 0)) return 0;
205 	    *widthPtr = w;
206 	    *heightPtr = h;
207 	    return 1;
208 	}
209     }
210     return 0;
211 }
212 
ChanReadPS(interp,chan,fileName,format,imageHandle,destX,destY,width,height,srcX,srcY)213 static int ChanReadPS(interp, chan, fileName, format, imageHandle,
214 	destX, destY, width, height, srcX, srcY)
215     Tcl_Interp *interp;
216     Tcl_Channel chan;
217     CONST char *fileName;
218     Tcl_Obj *format;
219     Tk_PhotoHandle imageHandle;
220     int destX, destY;
221     int width, height;
222     int srcX, srcY;
223 {
224     MFile handle;
225 
226     handle.data = (char *) chan;
227     handle.state = IMG_CHAN;
228 
229     return CommonReadPS(interp, &handle, format, imageHandle, destX, destY,
230 	    width, height, srcX, srcY);
231 }
232 
ObjReadPS(interp,data,format,imageHandle,destX,destY,width,height,srcX,srcY)233 static int ObjReadPS(interp, data, format, imageHandle,
234 	destX, destY, width, height, srcX, srcY)
235     Tcl_Interp *interp;
236     Tcl_Obj *data;
237     Tcl_Obj *format;
238     Tk_PhotoHandle imageHandle;
239     int destX, destY;
240     int width, height;
241     int srcX, srcY;
242 {
243     MFile handle;
244 
245     ImgReadInit(data,'%',&handle);
246 
247     return CommonReadPS(interp, &handle, format, imageHandle,
248 	    destX, destY, width, height, srcX, srcY);
249 }
250 
251 typedef struct myblock {
252     Tk_PhotoImageBlock ck;
253     int dummy; /* extra space for offset[3], in case it is not
254 		  included already in Tk_PhotoImageBlock */
255 } myblock;
256 
257 #define block bl.ck
258 
259 static int
CommonReadPS(interp,handle,format,imageHandle,destX,destY,width,height,srcX,srcY)260 CommonReadPS(interp, handle, format, imageHandle,
261 	destX, destY, width, height, srcX, srcY)
262     Tcl_Interp *interp;
263     MFile *handle;
264     Tcl_Obj *format;
265     Tk_PhotoHandle imageHandle;
266     int destX, destY;
267     int width, height;
268     int srcX, srcY;
269 {
270 #ifndef MAC_TCL
271     char *argv[10];
272     int len, i, j, fileWidth, fileHeight, maxintensity, index;
273     char *p, type;
274     unsigned char buffer[1025], *line = NULL, *line3 = NULL;
275 	char zoom[64], papersize[64];
276     Tcl_Channel chan;
277     Tcl_DString dstring;
278     myblock bl;
279     int zoomx, zoomy;
280 
281     index = parseFormat(format, &zoomx, &zoomy);
282     if (index < 0) {
283 	Tcl_AppendResult(interp, "invalid format: \"",
284 		ImgGetStringFromObj(format, NULL), "\"", (char *) NULL);
285 	return TCL_ERROR;
286     }
287     sprintf(zoom, "-r%dx%d", zoomx, zoomy);
288 
289     len = ImgRead(handle, buffer, 1024);
290     buffer[1024] = 0;
291     p = strstr(buffer,"%%BoundingBox:");
292     fileHeight = height + srcY;
293     if (p) {
294 	/* postscript */
295 	p += 14;
296 	srcX += (strtoul(p, &p, 0) * zoomx + 36) / 72;
297 	fileHeight += (strtoul(p, &p, 0) * zoomy + 36) / 72;
298 	strtoul(p, &p, 0);
299 	srcY -= (strtoul(p, &p, 0) * zoomy + 36) / 72;
300     } else {
301 	/* pdf */
302 
303 	/*
304 	 * Extract the pixel position of the upper left corner
305 	 * of the image from the file. How to do that????
306 	 * For now I just assume A4-size with 72 pixels/inch.
307 	 */
308 	srcX += (0 * zoomx + 36) / 72;
309 	srcY -= (792 * zoomy + 36) /72;
310     }
311 
312     sprintf(papersize, "-g%dx%d", srcX+width, fileHeight);
313 
314     argv[0] = "gs";
315     argv[1] = "-sDEVICE=ppmraw";
316     argv[2] = zoom;
317     argv[3] = papersize;
318     argv[4] = "-q";
319     argv[5] = "-dNOPAUSE";
320     argv[6] = "-sOutputFile=-";
321     argv[7] = "-";
322 
323     chan = Tcl_OpenCommandChannel(interp, 8, argv,
324 	    TCL_STDIN|TCL_STDOUT|TCL_STDERR|TCL_ENFORCE_MODE);
325     if (!chan) {
326 	return TCL_ERROR;
327     }
328     if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) {
329 	return TCL_ERROR;
330     }
331 
332     while (len > 0) {
333 	Tcl_Write(chan, (char *) buffer, 1024);
334 	len = ImgRead(handle, buffer, 1024);
335     }
336     Tcl_Write(chan,"\nquit\n", 6);
337     Tcl_Flush(chan);
338 
339     Tcl_DStringInit(&dstring);
340     len = Tcl_Gets(chan, &dstring);
341     p = Tcl_DStringValue(&dstring);
342     type = p[1];
343     if ((p[0] != 'P') || (type < '4') || (type > '6')) {
344 	Tcl_AppendResult(interp, "gs error: \"",
345 		p, "\"",(char *) NULL);
346 	return TCL_ERROR;
347     }
348     do {
349 	Tcl_DStringSetLength(&dstring, 0);
350 	Tcl_Gets(chan, &dstring);
351 	p = Tcl_DStringValue(&dstring);
352     } while (p[0] == '#');
353     fileWidth = strtoul(p, &p, 0);
354     srcY += (fileHeight = strtoul(p, &p, 0));
355 
356     if ((srcX + width) > fileWidth) {
357 	width = fileWidth - srcX;
358     }
359     if ((srcY + height) > fileHeight) {
360 	height = fileHeight - srcY;
361     }
362     if ((width <= 0) || (height <= 0)) {
363 	Tcl_Close(interp, chan);
364 	Tcl_DStringFree(&dstring);
365 	return TCL_OK;
366     }
367     Tk_PhotoExpand(imageHandle, destX + width, destY + height);
368 
369     maxintensity = strtoul(p, &p, 0);
370     if ((type != '4') && !maxintensity) {
371 	Tcl_DStringSetLength(&dstring, 0);
372 	Tcl_Gets(chan, &dstring);
373 	p = Tcl_DStringValue(&dstring);
374 	maxintensity = strtoul(p, &p, 0);
375     }
376     Tcl_DStringFree(&dstring);
377     line3 = (unsigned char *) ckalloc(3 * fileWidth);
378     block.pixelSize = 1;
379     block.pitch = block.width = width;
380     block.height = 1;
381     block.offset[0] = 0;
382     block.offset[1] = 0;
383     block.offset[2] = 0;
384     block.offset[3] = 0;
385     switch(type) {
386 	case '4':
387 	    i = (fileWidth+7)/8;
388 	    line = (unsigned char *) ckalloc(i);
389 	    while (srcY-- > 0) {
390 		Tcl_Read(chan,(char *) line, i);
391 	    }
392 	    block.pixelPtr = line3;
393 	    while (height--) {
394 	        Tcl_Read(chan, (char *) line, i);
395 	        for (j = 0; j < width; j++) {
396 		    line3[j] = ((line[(j+srcX)/8]>>(7-(j+srcX)%8) & 1)) ? 0 : 255;
397 	        }
398 		Tk_PhotoPutBlock(imageHandle, &block, destX, destY++, width, 1);
399 	    }
400 	    break;
401 	case '5':
402 	    line = (unsigned char *) ckalloc(fileWidth);
403 	    while (srcY-- > 0) {
404 		Tcl_Read(chan, (char *) line, fileWidth);
405 	    }
406 	    block.pixelPtr = line + srcX;
407 	    while (height--) {
408 		unsigned char *c = block.pixelPtr;
409 		Tcl_Read(chan, (char *) line, fileWidth);
410 		if (maxintensity != 255) {
411 		    for (j = width; j > 0; j--) {
412 			*c = (((int)*c) * maxintensity) / 255;
413 			c++;
414 		    }
415 		}
416 		Tk_PhotoPutBlock(imageHandle, &block, destX, destY++, width, 1);
417 	    }
418 	    break;
419 	case '6':
420 	    i = 3 * fileWidth;
421 	    line = NULL;
422 	    while (srcY-- > 0) {
423 		Tcl_Read(chan, (char *) line3, i);
424 	    }
425 	    block.pixelPtr = line3 + (3 * srcX);
426 	    block.pixelSize = 3;
427 	    block.offset[1] = 1;
428 	    block.offset[2] = 2;
429 	    while (height--) {
430 		unsigned char *c = block.pixelPtr;
431 		Tcl_Read(chan, (char *) line3, i);
432 		if (maxintensity != 255) {
433 		    for (j = (3 * width - 1); j >= 0; j--) {
434 			*c = (((int)*c) * maxintensity) / 255;
435 			c++;
436 		    }
437 		}
438 		Tk_PhotoPutBlock(imageHandle, &block, destX, destY++, width, 1);
439 	    }
440 	    break;
441     }
442     if (line) {
443 	ckfree((char *) line);
444     }
445     ckfree((char *) line3);
446     Tcl_Close(interp, chan);
447     Tcl_ResetResult(interp);
448     return TCL_OK;
449 #else
450     Tcl_AppendResult(interp, "Cannot read postscript file: not implemented",
451 	    (char *) NULL);
452     return TCL_ERROR;
453 #endif
454 }
ChanReadPDF(interp,chan,fileName,format,imageHandle,destX,destY,width,height,srcX,srcY)455 static int ChanReadPDF(interp, chan, fileName, format, imageHandle,
456 	destX, destY, width, height, srcX, srcY)
457     Tcl_Interp *interp;
458     Tcl_Channel chan;
459     CONST char *fileName;
460     Tcl_Obj *format;
461     Tk_PhotoHandle imageHandle;
462     int destX, destY;
463     int width, height;
464     int srcX, srcY;
465 {
466     return ChanReadPS(interp, chan, fileName, format, imageHandle, destX, destY,
467 	    width, height, srcX, srcY);
468 }
469 
ObjReadPDF(interp,data,format,imageHandle,destX,destY,width,height,srcX,srcY)470 static int ObjReadPDF(interp, data, format, imageHandle,
471 	destX, destY, width, height, srcX, srcY)
472     Tcl_Interp *interp;
473     Tcl_Obj *data;
474     Tcl_Obj *format;
475     Tk_PhotoHandle imageHandle;
476     int destX, destY;
477     int width, height;
478     int srcX, srcY;
479 {
480     return ObjReadPS(interp, data, format, imageHandle,
481 	    destX, destY, width, height, srcX, srcY);
482 }
483 
ChanWritePS(interp,filename,format,blockPtr)484 static int ChanWritePS(interp, filename, format, blockPtr)
485     Tcl_Interp *interp;
486     CONST char *filename;
487     Tcl_Obj *format;
488     Tk_PhotoImageBlock *blockPtr;
489 {
490     Tcl_Channel chan;
491     MFile handle;
492     int result;
493 
494     chan = ImgOpenFileChannel(interp, filename, 0644);
495     if (!chan) {
496 	return TCL_ERROR;
497     }
498 
499     handle.data = (char *) chan;
500     handle.state = IMG_CHAN;
501 
502     result = CommonWritePS(interp, &handle, format, blockPtr);
503     if (Tcl_Close(interp, chan) == TCL_ERROR) {
504 	return TCL_ERROR;
505     }
506     return result;
507 }
508 
StringWritePS(interp,dataPtr,format,blockPtr)509 static int StringWritePS(interp, dataPtr, format, blockPtr)
510     Tcl_Interp *interp;
511     Tcl_DString *dataPtr;
512     Tcl_Obj *format;
513     Tk_PhotoImageBlock *blockPtr;
514 {
515     MFile handle;
516     int result;
517     Tcl_DString data;
518     ImgFixStringWriteProc(&data, &interp, &dataPtr, &format, &blockPtr);
519     ImgWriteInit(dataPtr, &handle);
520     result = CommonWritePS(interp, &handle, format, blockPtr);
521     ImgPutc(IMG_DONE, &handle);
522     if ((result == TCL_OK) && (dataPtr == &data)) {
523 	Tcl_DStringResult(interp, dataPtr);
524     }
525     return result;
526 }
527 
CommonWritePS(interp,handle,format,blockPtr)528 static int CommonWritePS(interp, handle, format, blockPtr)
529     Tcl_Interp *interp;
530     MFile *handle;
531     Tcl_Obj *format;
532     Tk_PhotoImageBlock *blockPtr;
533 {
534     return TCL_OK;
535 }
536 
ChanMatchPDF(interp,chan,fileName,format,widthPtr,heightPtr)537 static int ChanMatchPDF(interp, chan, fileName, format, widthPtr, heightPtr)
538     Tcl_Interp *interp;
539     Tcl_Channel chan;
540     CONST char *fileName;
541     Tcl_Obj *format;
542     int *widthPtr, *heightPtr;
543 {
544     MFile handle;
545 
546     ImgFixChanMatchProc(&interp, &chan, &fileName, &format, &widthPtr, &heightPtr);
547 
548     handle.data = (char *) chan;
549     handle.state = IMG_CHAN;
550 
551     return CommonMatchPDF(&handle, format, widthPtr, heightPtr);
552 }
553 
ObjMatchPDF(interp,data,format,widthPtr,heightPtr)554 static int ObjMatchPDF(interp, data, format, widthPtr, heightPtr)
555     Tcl_Interp *interp;
556     Tcl_Obj *data;
557     Tcl_Obj *format;
558     int *widthPtr, *heightPtr;
559 {
560     MFile handle;
561 
562     ImgFixObjMatchProc(&interp, &data, &format, &widthPtr, &heightPtr);
563 
564     if (!ImgReadInit(data, '%', &handle)) {
565 	return 0;
566     }
567 
568     return CommonMatchPDF(&handle, format, widthPtr, heightPtr);
569 }
570 
CommonMatchPDF(handle,format,widthPtr,heightPtr)571 static int CommonMatchPDF(handle, format, widthPtr, heightPtr)
572     MFile *handle;
573     Tcl_Obj *format;
574     int *widthPtr, *heightPtr;
575 {
576     unsigned char buf[41];
577     int zoomx, zoomy, w, h;
578 
579     if ((ImgRead(handle, (char *) buf, 5) != 5)
580 	    || (strncmp("%PDF-", (char *) buf, 5) != 0)) {
581 	return 0;
582     }
583 
584     /* Here w and h should be set to the bounding box of the pdf
585      * data. But I don't know how to extract that from the file.
586      * For now I just assume A4-size with 72 pixels/inch. If anyone
587      * has a better idea, please mail to <j.nijtmans@chello.nl>.
588      */
589 
590     w = 612/10;
591     h = 792/10;
592 
593     if (parseFormat(format, &zoomx, &zoomy) >= 0) {
594 	w = (w * zoomx + 36) / 72;
595 	h = (h * zoomy + 36) / 72;
596     }
597     if ((w <= 0) || (h <= 0)) return 0;
598     *widthPtr = w;
599     *heightPtr = h;
600     return 1;
601 }
602