Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <memdraw.h>
5
#include <bio.h>
6
#include "pslib.h"
7
/* implement PsLib;
8
/* 
9
/* include "sys.m";
10
/* 	sys: Sys;
11
/* 
12
/* include "draw.m";
13
/* 	draw : Draw;
14
/* Image, Display,Rect,Point : import draw;
15
/* 
16
/* include "bufio.m";
17
/* 	bufmod : Bufio;
18
/* 
19
/* include "tk.m";
20
/* 	tk: Tk;
21
/* 	Toplevel: import tk;
22
/* 
23
/* Iobuf : import bufmod;
24
/* 
25
/* include "string.m";
26
/* 	str : String;
27
/* 
28
/* include "daytime.m";
29
/* 	time : Daytime;
30
/* 
31
/* include "pslib.m";
32
/* 
33
/* ASCII,RUNE,IMAGE : con iota;
34
/* 
35
*/
36
struct iteminfo {
37
	int itype;
38
	int offset;		/* offset from the start of line. */
39
	int width;		/* width.... */
40
	int ascent;		/* ascent of the item */
41
	int font;		/* font */
42
	int line;		/* line its on */
43
	char *buf;	
44
};
45
 
46
struct lineinfo {
47
	int xorg;
48
	int yorg;
49
	int width;
50
	int height;
51
	int ascent;
52
};
53
 
54
 
55
/* font_arr := array[256] of {* => (-1,"")};
56
/* remap := array[20] of (string,string);
57
/* 
58
/* PXPI : con 100;
59
/* PTPI : con 100;
60
/* 
61
*/
62
char *noinit = "pslib not properly initialized";
63
/* 
64
*/
65
static int boxes;
66
static int debug;
67
static int totitems;
68
static int totlines;
69
static int curfont;
70
static char *def_font;
71
static int def_font_type;
72
static int curfonttype;
73
static int pagestart;
74
static int started;
75
 
76
static int bps;
77
static int width;
78
static int height;
79
static int iwidth;
80
static int iheight;
81
static int xstart;
82
static int ystart;
83
static double xmagnification = 1.0, ymagnification = 1.0;
84
static int rotation = 0;
85
static int landscape = 0;
86
static char *Patch = nil;
87
 
88
/* ctxt 		: ref Draw->Context;
89
/* t 		: ref Toplevel;
90
*/
91
char*
92
psinit(int box, int deb) { /* d: ref Toplevel, */
93
/* 	t=d; */
94
	debug = deb;
95
	totlines=0;
96
	totitems=0;
97
	pagestart=0;
98
	boxes=box; /* #box; */
99
	curfont=0;
100
/* 	e := loadfonts();
101
/* 	if (e != "")
102
/* 		return e;
103
*/
104
	started=1;
105
	return "";
106
}
107
 
108
/* stats() : (int,int,int)
109
/* {
110
/* 	return 	(totitems,totlines,curfont);
111
/* }
112
/* 
113
/* loadfonts() : string
114
/* {
115
/* 	input : string;
116
/* 	iob:=bufmod->open("/fonts/psrename",bufmod->OREAD);
117
/* 	if (iob==nil)
118
/* 		return sys->sprint("can't open /fonts/psrename: %r");
119
/* 	i:=0;
120
/* 	while((input=iob.gets('\n'))!=nil){
121
/* 		(tkfont,psfont):=str->splitl(input," ");
122
/* 		psfont=psfont[1:len psfont -1];
123
/* 		remap[i]=(tkfont,psfont);
124
/* 		i++;
125
/* 	}
126
/* 	return "";
127
/* }
128
/* 
129
*/
130
static char *username;
131
 
132
int
133
preamble(Biobuf *ioutb, Rectangle bb) {
134
 
135
	if (!started) return 1;
136
	username = getuser();
137
	if(bb.max.x == 0 && bb.max.y == 0) {
138
		bb.max.x = 612;
139
		bb.max.y = 792;
140
	}
141
	Bprint(ioutb, "%%!PS-Adobe-3.0\n");
142
	Bprint(ioutb, "%%%%Creator: PsLib 1.0 (%s)\n",username);
143
	Bprint(ioutb, "%%%%CreationDate: %s", ctime(time(nil)));
144
	Bprint(ioutb, "%%%%Pages: (atend) \n");
145
	Bprint(ioutb, "%%%%BoundingBox: %d %d %d %d\n", bb.min.x, bb.min.y, bb.max.x, bb.max.y);
146
	Bprint(ioutb, "%%%%EndComments\n");
147
	Bprint(ioutb, "%%%%BeginProlog\n");
148
	Bprint(ioutb, "/doimage {\n");
149
	Bprint(ioutb, "/grey exch def\n");
150
	Bprint(ioutb, "/bps exch def\n");
151
	Bprint(ioutb, "/width exch def\n");
152
	Bprint(ioutb, "/height exch def\n");
153
	Bprint(ioutb, "/xstart exch def\n");
154
	Bprint(ioutb, "/ystart exch def\n");
155
	Bprint(ioutb, "/iwidth exch def\n");
156
	Bprint(ioutb, "/ascent exch def\n");
157
	Bprint(ioutb, "/iheight exch def\n");
158
	Bprint(ioutb, "gsave\n");
159
	if(boxes)
160
		Bprint(ioutb, "xstart ystart iwidth iheight rectstroke\n");
161
/*	# if bps==8, use inferno colormap; else (bps < 8) it's grayscale or true color */
162
	Bprint(ioutb, "bps 8 eq grey false eq and {\n");
163
	Bprint(ioutb, " [/Indexed /DeviceRGB 255 <\n");
164
	Bprint(ioutb, "  ffffff ffffaa ffff55 ffff00 ffaaff ffaaaa ffaa55 ffaa00 ff55ff ff55aa ff5555 ff5500\n");
165
	Bprint(ioutb, "  ff00ff ff00aa ff0055 ff0000 ee0000 eeeeee eeee9e eeee4f eeee00 ee9eee ee9e9e ee9e4f\n");
166
	Bprint(ioutb, "  ee9e00 ee4fee ee4f9e ee4f4f ee4f00 ee00ee ee009e ee004f dd0049 dd0000 dddddd dddd93\n");
167
	Bprint(ioutb, "  dddd49 dddd00 dd93dd dd9393 dd9349 dd9300 dd49dd dd4993 dd4949 dd4900 dd00dd dd0093\n");
168
	Bprint(ioutb, "  cc0088 cc0044 cc0000 cccccc cccc88 cccc44 cccc00 cc88cc cc8888 cc8844 cc8800 cc44cc\n");
169
	Bprint(ioutb, "  cc4488 cc4444 cc4400 cc00cc aaffaa aaff55 aaff00 aaaaff bbbbbb bbbb5d bbbb00 aa55ff\n");
170
	Bprint(ioutb, "  bb5dbb bb5d5d bb5d00 aa00ff bb00bb bb005d bb0000 aaffff 9eeeee 9eee9e 9eee4f 9eee00\n");
171
	Bprint(ioutb, "  9e9eee aaaaaa aaaa55 aaaa00 9e4fee aa55aa aa5555 aa5500 9e00ee aa00aa aa0055 aa0000\n");
172
	Bprint(ioutb, "  990000 93dddd 93dd93 93dd49 93dd00 9393dd 999999 99994c 999900 9349dd 994c99 994c4c\n");
173
	Bprint(ioutb, "  994c00 9300dd 990099 99004c 880044 880000 88cccc 88cc88 88cc44 88cc00 8888cc 888888\n");
174
	Bprint(ioutb, "  888844 888800 8844cc 884488 884444 884400 8800cc 880088 55ff55 55ff00 55aaff 5dbbbb\n");
175
	Bprint(ioutb, "  5dbb5d 5dbb00 5555ff 5d5dbb 777777 777700 5500ff 5d00bb 770077 770000 55ffff 55ffaa\n");
176
	Bprint(ioutb, "  4fee9e 4fee4f 4fee00 4f9eee 55aaaa 55aa55 55aa00 4f4fee 5555aa 666666 666600 4f00ee\n");
177
	Bprint(ioutb, "  5500aa 660066 660000 4feeee 49dddd 49dd93 49dd49 49dd00 4993dd 4c9999 4c994c 4c9900\n");
178
	Bprint(ioutb, "  4949dd 4c4c99 555555 555500 4900dd 4c0099 550055 550000 440000 44cccc 44cc88 44cc44\n");
179
	Bprint(ioutb, "  44cc00 4488cc 448888 448844 448800 4444cc 444488 444444 444400 4400cc 440088 440044\n");
180
	Bprint(ioutb, "  00ff00 00aaff 00bbbb 00bb5d 00bb00 0055ff 005dbb 007777 007700 0000ff 0000bb 000077\n");
181
	Bprint(ioutb, "  333333 00ffff 00ffaa 00ff55 00ee4f 00ee00 009eee 00aaaa 00aa55 00aa00 004fee 0055aa\n");
182
	Bprint(ioutb, "  006666 006600 0000ee 0000aa 000066 222222 00eeee 00ee9e 00dd93 00dd49 00dd00 0093dd\n");
183
	Bprint(ioutb, "  009999 00994c 009900 0049dd 004c99 005555 005500 0000dd 000099 000055 111111 00dddd\n");
184
	Bprint(ioutb, "  00cccc 00cc88 00cc44 00cc00 0088cc 008888 008844 008800 0044cc 004488 004444 004400\n");
185
	Bprint(ioutb, "  0000cc 000088 000044 000000>\n");
186
	Bprint(ioutb, " ] setcolorspace\n");
187
	Bprint(ioutb, " /decodemat [0 255] def\n");
188
	Bprint(ioutb, "}\n");
189
/*	# else, bps != 8 */
190
	Bprint(ioutb, "{\n");
191
/* is it greyscale or is it 24-bit color? */
192
	Bprint(ioutb, " grey true eq {\n");
193
	Bprint(ioutb, "  [/DeviceGray] setcolorspace\n");
194
	Bprint(ioutb, "  /decodemat [1 0] def\n");
195
	Bprint(ioutb, " }\n");
196
	Bprint(ioutb, " {\n");
197
/* must be color */
198
	Bprint(ioutb, "  [/DeviceRGB] setcolorspace\n");
199
	Bprint(ioutb, "  /bps 8 def\n");
200
	Bprint(ioutb, "  /decodemat [1 0 1 0 1 0] def\n");
201
	Bprint(ioutb, " }\n");
202
	Bprint(ioutb, " ifelse\n");
203
	Bprint(ioutb, "}\n");
204
	Bprint(ioutb, "ifelse\n");
205
	Bprint(ioutb, "/xmagnification %g def\n", xmagnification);
206
	Bprint(ioutb, "/ymagnification %g def\n", ymagnification);
207
	Bprint(ioutb, "/rotation %d def\n", rotation);
208
	Bprint(ioutb, "xstart ystart translate rotation rotate\n");
209
	Bprint(ioutb, "iwidth xmagnification mul iheight ymagnification mul scale\n");
210
	Bprint(ioutb, "<<\n");
211
	Bprint(ioutb, " /ImageType 1\n");
212
	Bprint(ioutb, " /Width width \n");
213
	Bprint(ioutb, " /Height height \n");
214
	Bprint(ioutb, " /BitsPerComponent bps %% bits/sample\n");
215
	Bprint(ioutb, " /Decode decodemat %% Brazil/Inferno cmap or DeviceGray value\n");
216
	Bprint(ioutb, " /ImageMatrix [width 0 0 height neg 0 height]\n");
217
	Bprint(ioutb, " /DataSource currentfile /ASCII85Decode filter\n");
218
	Bprint(ioutb, ">> \n");
219
	Bprint(ioutb, "image\n");
220
	Bprint(ioutb, "grestore\n");
221
	Bprint(ioutb, "} def\n");
222
	Bprint(ioutb, "%%%%EndProlog\n");
223
	if (Patch != nil)
224
		Bprint(ioutb, "%s\n", Patch);
225
	return 0;	
226
}
227
 
228
int
229
trailer(Biobuf *ioutb ,int pages) {
230
	if(!started)
231
		return 1;
232
	Bprint(ioutb, "%%%%Trailer\n%%%%Pages: %d\n%%%%EOF\n", pages);
233
	return 0;
234
}
235
 
236
void
237
printnewpage(int pagenum, int end, Biobuf *ioutb)
238
{
239
	if (!started) return;
240
	if (end){			
241
/*		# bounding box */
242
		if (boxes){
243
			Bprint(ioutb, "18 18 moveto 594 18 lineto 594 774 lineto 18 774 lineto closepath stroke\n");
244
		}
245
		Bprint(ioutb, "showpage\n%%%%EndPage %d %d\n", pagenum, pagenum);
246
	} else 
247
		Bprint(ioutb, "%%%%Page: %d %d\n", pagenum, pagenum);
248
}
249
 
250
/* int
251
/* printimage(FILE *ioutb, struct lineinfo line, struct iteminfo imag) {
252
/* 	int RM;
253
/* 
254
/* 	RM=612-18;
255
/* 	class:=tk->cmd(t,"winfo class "+imag.buf);
256
/* #sys->print("Looking for [%s] of type [%s]\n",imag.buf,class);
257
/* 	if (line.xorg+imag.offset+imag.width>RM)
258
/* 		imag.width=RM-line.xorg-imag.offset;
259
/* 	case class {
260
/* 		"button" or "menubutton" =>
261
/* 			# try to get the text out and print it....
262
/* 			ioutb.puts(sys->sprint("%d %d moveto\n",line.xorg+imag.offset,
263
/* 							line.yorg));
264
/* 			msg:=tk->cmd(t,sys->sprint("%s cget -text",imag.buf));
265
/* 			ft:=tk->cmd(t,sys->sprint("%s cget -font",imag.buf));
266
/* 			sys->print("font is [%s]\n",ft);
267
/* 			ioutb.puts(sys->sprint("%d %d %d %d rectstroke\n",
268
/* 						line.xorg+imag.offset,line.yorg,imag.width,
269
/* 						line.height));
270
/* 			return (class,msg);
271
/* 		"label" =>
272
/* 			(im,im2,err) := tk->imageget(t,imag.buf);
273
/* 			if (im!=nil){
274
/* 				bps := 1<<im.ldepth;
275
/* 				ioutb.puts(sys->sprint("%d %d %d %d %d %d %d %d doimage\n",
276
/* 						im.r.dy(),line.ascent,im.r.dx(),line.yorg,
277
/* 						line.xorg+imag.offset,im.r.dy(), im.r.dx(), bps));
278
/* 				imagebits(ioutb,im);
279
/* 			}
280
/* 			return (class,"");
281
/* 		"entry" =>
282
/* 			ioutb.puts(sys->sprint("%d %d moveto\n",line.xorg+imag.offset,
283
/* 					line.yorg));
284
/* 			ioutb.puts(sys->sprint("%d %d %d %d rectstroke\n",
285
/* 					line.xorg+imag.offset,line.yorg,imag.width,
286
/* 					line.height));
287
/* 			return (class,"");
288
/* 		* =>
289
/* 			sys->print("Unhandled class [%s]\n",class);
290
/* 			return (class,"Error");
291
/* 		
292
/* 	}
293
/* 	return ("","");	
294
/* }
295
/* 
296
/* printline(ioutb: ref Iobuf,line : lineinfo,items : array of iteminfo)
297
/* {
298
/* 	xstart:=line.xorg;
299
/* 	wid:=xstart;
300
/* 	# items
301
/* 	if (len items == 0) return;
302
/* 	for(j:=0;j<len items;j++){
303
/* 		msg:="";
304
/* 		class:="";
305
/* 		if (items[j].itype==IMAGE)
306
/* 			(class,msg)=printimage(ioutb,line,items[j]);
307
/* 		if (items[j].itype!=IMAGE || class=="button"|| class=="menubutton"){
308
/* 			setfont(ioutb,items[j].font);
309
/* 			if (msg!=""){ 
310
/* 				# position the text in the center of the label
311
/* 				# moveto curpoint
312
/* 				# (msg) stringwidth pop xstart sub 2 div
313
/* 				ioutb.puts(sys->sprint("%d %d moveto\n",xstart+items[j].offset,
314
/* 						line.yorg+line.height-line.ascent));
315
/* 				ioutb.puts(sys->sprint("(%s) dup stringwidth pop 2 div",
316
/* 								msg));
317
/* 				ioutb.puts(" 0 rmoveto show\n");
318
/* 			}
319
/* 			else {
320
/* 				ioutb.puts(sys->sprint("%d %d moveto\n",
321
/* 					xstart+items[j].offset,line.yorg+line.height
322
/* 					-line.ascent));
323
/* 				ioutb.puts(sys->sprint("(%s) show\n",items[j].buf));
324
/* 			}
325
/* 		}
326
/* 		wid=xstart+items[j].offset+items[j].width;
327
/* 	}
328
/* 	if (boxes)
329
/* 		ioutb.puts(sys->sprint("%d %d %d %d rectstroke\n",line.xorg,line.yorg,
330
/* 									wid,line.height));
331
/* }
332
/* 
333
/* setfont(ioutb: ref Iobuf,font : int){
334
/* 	ftype : int;
335
/* 	fname : string;
336
/* 	if ((curfonttype&font)!=curfonttype){
337
/* 		for(f:=0;f<curfont;f++){
338
/* 			(ftype,fname)=font_arr[f];
339
/* 				if ((ftype&font)==ftype)
340
/* 					break;
341
/* 		}
342
/* 		if (f==curfont){
343
/* 			fname=def_font;
344
/* 			ftype=def_font_type;
345
/* 		}
346
/* 		ioutb.puts(sys->sprint("%s setfont\n",fname));
347
/* 		curfonttype=ftype;
348
/* 	}
349
/* }
350
/* 	
351
/* parseTkline(ioutb: ref Iobuf,input : string) : string
352
/* {
353
/* 	if (!started) return noinit;
354
/* 	thisline : lineinfo;
355
/* 	PS:=792-18-18;	# page size in points	
356
/* 	TM:=792-18;	# top margin in points
357
/* 	LM:=18;		# left margin 1/4 in. in
358
/* 	BM:=18;		# bottom margin 1/4 in. in
359
/* 	x : int;
360
/* 	(x,input)=str->toint(input,10);
361
/* 	thisline.xorg=(x*PTPI)/PXPI;
362
/* 	(x,input)=str->toint(input,10);
363
/* 	thisline.yorg=(x*PTPI)/PXPI;
364
/* 	(x,input)=str->toint(input,10);
365
/* 	thisline.width=(x*PTPI)/PXPI;
366
/* 	(x,input)=str->toint(input,10);
367
/* 	thisline.height=(x*PTPI)/PXPI;
368
/* 	(x,input)=str->toint(input,10);
369
/* 	thisline.ascent=(x*PTPI)/PXPI;
370
/* 	(x,input)=str->toint(input,10);
371
/* 	# thisline.numitems=x;
372
/* 	if (thisline.width==0 || thisline.height==0)
373
/* 		return "";
374
/* 	if (thisline.yorg+thisline.height-pagestart>PS){
375
/* 		pagestart=thisline.yorg;
376
/* 		return "newpage";
377
/* 		# must resend this line....
378
/* 	}
379
/* 	thisline.yorg=TM-thisline.yorg-thisline.height+pagestart;
380
/* 	thisline.xorg+=LM;
381
/* 	(items, err) :=getline(totlines,input);
382
/* 	if(err != nil)
383
/* 		return err;
384
/* 	totitems+=len items;
385
/* 	totlines++;
386
/* 	printline(ioutb,thisline,items);
387
/* 	return "";
388
/* }
389
/* 	
390
/* 
391
/* getfonts(input: string) : string
392
/* {
393
/* 	if (!started) return "Error";
394
/* 	tkfont,psfont : string;
395
/* 	j : int;
396
/* 	retval := "";
397
/* 	if (input[0]=='%')
398
/* 			return "";
399
/* 	# get a line of the form 
400
/* 	# 5::/fonts/lucida/moo.16.font
401
/* 	# translate it to...
402
/* 	# 32 f32.16
403
/* 	# where 32==1<<5 and f32.16 is a postscript function that loads the 
404
/* 	# appropriate postscript font (from remap)
405
/* 	# and writes it to fonts....
406
/* 	(bits,font):=str->toint(input,10);
407
/* 	if (bits!=-1)
408
/* 		bits=1<<bits;
409
/* 	else{
410
/* 		bits=1;
411
/* 		def_font_type=bits;
412
/* 		curfonttype=def_font_type;
413
/* 	}
414
/* 	font=font[2:];
415
/* 	for(i:=0;i<len remap;i++){
416
/* 		(tkfont,psfont)=remap[i];
417
/* 		if (tkfont==font)
418
/* 			break;
419
/* 	}
420
/* 	if (i==len remap)
421
/* 		psfont="Times-Roman";
422
/* 	(font,nil)=str->splitr(font,".");
423
/* 	(nil,font)=str->splitr(font[0:len font-1],".");
424
/* 	(fsize,nil):=str->toint(font,10);
425
/* 	fsize=(PTPI*3*fsize)/(2*PXPI);
426
/* 	enc_font:="f"+string bits+"."+string fsize;
427
/* 	ps_func:="/"+enc_font+" /"+psfont+" findfont "+string fsize+
428
/* 							" scalefont def\n";
429
/* 	sy_font:="sy"+string fsize;
430
/* 	xtra_func:="/"+sy_font+" /Symbol findfont "+string fsize+
431
/* 							" scalefont def\n";
432
/* 	for(i=0;i<len font_arr;i++){
433
/* 		(j,font)=font_arr[i];
434
/* 		if (j==-1) break;
435
/* 	}
436
/* 	if (j==len font_arr)
437
/* 		return "Error";
438
/* 	font_arr[i]=(bits,enc_font);
439
/* 	if (bits==1)
440
/* 		def_font=enc_font;
441
/* 	curfont++;
442
/* 	retval+= ps_func;
443
/* 	retval+= xtra_func;	
444
/* 	return retval;
445
/* }
446
/* 
447
/* deffont() : string
448
/* {
449
/* 	return def_font;
450
/* }
451
/* 	
452
/* getline(k : int,  input : string) : (array of iteminfo, string)
453
/* {
454
/* 	lineval,args : string;
455
/* 	j, nb : int;
456
/* 	lw:=0;
457
/* 	wid:=0;
458
/* 	flags:=0;
459
/* 	item_arr := array[32] of {* => iteminfo(-1,-1,-1,-1,-1,-1,"")};
460
/* 	curitem:=0;
461
/* 	while(input!=nil){
462
/* 		(nil,input)=str->splitl(input,"[");
463
/* 		if (input==nil)
464
/* 			break;
465
/* 		com:=input[1];
466
/* 		input=input[2:];
467
/* 		case com {
468
/* 			'A' =>
469
/* 				nb=0;
470
/* 				# get the width of the item
471
/* 				(wid,input)=str->toint(input,10);
472
/* 				wid=(wid*PTPI)/PXPI;
473
/* 				if (input[0]!='{')
474
/* 					return (nil, sys->sprint(
475
/* 						"line %d item %d Bad Syntax : '{' expected",
476
/* 							k,curitem));
477
/* 				# get the args.
478
/* 				(args,input)=str->splitl(input,"}");
479
/* 				# get the flags.
480
/* 				# assume there is only one int flag..
481
/* 				(flags,args)=str->toint(args[1:],16);
482
/* 				if (args!=nil && debug){
483
/* 					sys->print("line %d item %d extra flags=%s\n",
484
/* 							k,curitem,args);
485
/* 				}
486
/* 				if (flags<1024) flags=1;
487
/* 				item_arr[curitem].font=flags;
488
/* 				item_arr[curitem].offset=lw;
489
/* 				item_arr[curitem].width=wid;
490
/* 				lw+=wid;
491
/* 				for(j=1;j<len input;j++){
492
/* 					if ((input[j]==')')||(input[j]=='('))
493
/* 							lineval[len lineval]='\\';
494
/* 					if (input[j]=='[')
495
/* 						nb++;
496
/* 					if (input[j]==']')
497
/* 						if (nb==0)
498
/* 							break;
499
/* 						else 
500
/* 							nb--;
501
/* 					lineval[len lineval]=input[j];
502
/* 				}
503
/* 				if (j<len input)
504
/* 					input=input[j:];
505
/* 				item_arr[curitem].buf=lineval;
506
/* 				item_arr[curitem].line=k;
507
/* 				item_arr[curitem].itype=ASCII;
508
/* 				curitem++;
509
/* 				lineval="";
510
/* 			'R' =>
511
/* 				nb=0;
512
/* 				# get the width of the item
513
/* 				(wid,input)=str->toint(input,10);
514
/* 				wid=(wid*PTPI)/PXPI;
515
/* 				if (input[0]!='{')
516
/* 					return (nil, "Bad Syntax : '{' expected");
517
/* 				# get the args.
518
/* 				(args,input)=str->splitl(input,"}");
519
/* 				# get the flags.
520
/* 				# assume there is only one int flag..
521
/* 				(flags,args)=str->toint(args[1:],16);
522
/* 				if (args!=nil && debug){
523
/* 					sys->print("line %d item %d Bad Syntax args=%s",
524
/* 							k,curitem,args);
525
/* 				}
526
/* 				item_arr[curitem].font=flags;
527
/* 				item_arr[curitem].offset=lw;
528
/* 				item_arr[curitem].width=wid;
529
/* 				lw+=wid;
530
/* 				for(j=1;j<len input;j++){
531
/* 					if (input[j]=='[')
532
/* 						nb++;
533
/* 					if (input[j]==']')
534
/* 						if (nb==0)
535
/* 							break;
536
/* 						else 
537
/* 							nb--;
538
/* 					case input[j] {
539
/* 						8226 => # bullet
540
/* 							lineval+="\\267 ";
541
/* 						169 =>  # copyright
542
/* 							lineval+="\\251 ";
543
/* 							curitem++;			
544
/* 						* =>
545
/* 							lineval[len lineval]=input[j];
546
/* 					}
547
/* 				}
548
/* 				if (j>len input)
549
/* 					input=input[j:];
550
/* 				item_arr[curitem].buf=lineval;
551
/* 				item_arr[curitem].line=k;
552
/* 				item_arr[curitem].itype=RUNE;
553
/* 				curitem++;
554
/* 				lineval="";
555
/* 			'N' or 'C'=>
556
/* 				# next item
557
/* 				for(j=0;j<len input;j++)
558
/* 					if (input[j]==']')
559
/* 						break;
560
/* 				if (j>len input)
561
/* 					input=input[j:];
562
/* 			'T' =>
563
/* 				(wid,input)=str->toint(input,10);
564
/* 				wid=(wid*PTPI)/PXPI;
565
/* 				item_arr[curitem].offset=lw;
566
/* 				item_arr[curitem].width=wid;
567
/* 				lw+=wid;
568
/* 				lineval[len lineval]='\t';
569
/* 				# next item
570
/* 				for(j=0;j<len input;j++)
571
/* 					if (input[j]==']')
572
/* 						break;
573
/* 				if (j>len input)
574
/* 					input=input[j:];
575
/* 				item_arr[curitem].buf=lineval;
576
/* 				item_arr[curitem].line=k;
577
/* 				item_arr[curitem].itype=ASCII;
578
/* 				curitem++;
579
/* 				lineval="";
580
/* 			'W' =>
581
/* 				(wid,input)=str->toint(input,10);
582
/* 				wid=(wid*PTPI)/PXPI;
583
/* 				item_arr[curitem].offset=lw;
584
/* 				item_arr[curitem].width=wid;
585
/* 				item_arr[curitem].itype=IMAGE;
586
/* 				lw+=wid;
587
/* 				# next item
588
/* 				for(j=1;j<len input;j++){
589
/* 					if (input[j]==']')
590
/* 						break;
591
/* 					lineval[len lineval]=input[j];
592
/* 				}
593
/* 				item_arr[curitem].buf=lineval;
594
/* 				if (j>len input)
595
/* 					input=input[j:];
596
/* 				curitem++;
597
/* 				lineval="";
598
/* 			* =>
599
/* 				# next item
600
/* 				for(j=0;j<len input;j++)
601
/* 					if (input[j]==']')
602
/* 						break;
603
/* 				if (j>len input)
604
/* 					input=input[j:];
605
/* 				
606
/* 		}
607
/* 	}
608
/* 	return (item_arr[0:curitem], "");	
609
/* }
610
*/
611
 
612
void
613
cmap2ascii85(uchar *b, uchar *c) {
614
	int i;
615
	unsigned long i1;
616
 
617
/*	fprintf(stderr, "addr=0x%x %x %x %x %x\n", b, b[0], b[1], b[2], b[3]); */
618
	b--;	/* one-index b */
619
	c--;	/* one-index c */
620
	i1 = (b[1]<<24)+(b[2]<<16)+(b[3]<<8)+b[4];
621
	if(i1 == 0){
622
		c[1] = 'z';
623
		c[2] = '\0';
624
		return;
625
	}
626
	for(i=0; i<=4; i++){
627
		c[5-i] = '!' + (i1 % 85);
628
		i1 /= 85;
629
	}
630
	c[6] = '\0';
631
}
632
 
633
static uchar *arr = nil;
634
ulong	onesbits = ~0;
635
void
636
imagebits(Biobuf *ioutb, Memimage *im)
637
{
638
	int spb;
639
	int bitoff;
640
	int j, n, n4, i, bpl, nrest;
641
	int lsf;
642
	uchar c85[6], *data, *src, *dst;
643
	Memimage *tmp;
644
	Rectangle r;
645
 
646
	tmp = nil;
647
	if (debug)
648
		fprint(2, "imagebits, r=%d %d %d %d, depth=%d\n",
649
			im->r.min.x, im->r.min.y, im->r.max.x, im->r.max.y, im->depth);
650
	width = Dx(im->r);
651
	height = Dy(im->r);
652
	bps = im->depth;	/* # bits per sample */
653
	bitoff = 0;		/* # bit offset of beginning sample within first byte */
654
	if (bps < 8) {
655
		spb = 8 / bps;
656
		bitoff = (im->r.min.x % spb) * bps;
657
	}
658
	if (bitoff != 0) {
659
/* 		# Postscript image wants beginning of line at beginning of byte */
660
		r = im->r;
661
		r.min.x -= bitoff/im->depth;
662
		r.max.x -= bitoff/im->depth;
663
		tmp = allocmemimage(r, im->chan);
664
		if(tmp == nil){
665
			fprint(2, "p9bitpost: allocmemimage failed: %r\n");
666
			exits("alloc");
667
		}
668
		memimagedraw(tmp, r, im, im->r.min, nil, ZP, S);
669
		im = tmp;
670
	}
671
	lsf = 0;
672
	/* compact data to remove word-boundary padding */
673
	bpl = bytesperline(im->r, im->depth);
674
	n = bpl*Dy(im->r);
675
	data = malloc(n);
676
	if(data == nil){
677
		fprint(2, "p9bitpost: malloc failed: %r\n");
678
		exits("malloc");
679
	}
680
	for(i=0; i<Dy(im->r); i++){
681
		/* memmove(data+bpl*i, byteaddr(im, Pt(im->r.min.x, im->r.min.y+i)), bpl); with inversion */
682
		dst = data+bpl*i;
683
		src = byteaddr(im, Pt(im->r.min.x, im->r.min.y+i));
684
		for(j=0; j<bpl; j++)
685
			*dst++ = 255 - *src++;
686
	}
687
	n4 = (n / 4) * 4;
688
	for (i = 0; i < n4; i += 4){
689
		cmap2ascii85(data+i, c85);
690
		lsf += strlen((char *)c85);
691
		Bprint(ioutb, "%s", (char *)c85);
692
		if (lsf > 74) {
693
			Bprint(ioutb, "\n");
694
			lsf = 0;
695
		}
696
	}
697
	nrest = n - n4;
698
	if (nrest != 0) {
699
		uchar foo[4];
700
 
701
		for (i=0; i<nrest; i++)
702
			foo[i] = data[n4+i];
703
		for (i=nrest; i<4; i++)
704
			foo[i] = '\0';
705
		cmap2ascii85(foo, c85);
706
		if (strcmp((char *)c85, "z") == 0 )
707
			strcpy((char *)c85, "!!!!!");
708
		Bprint(ioutb, "%.*s", nrest+1, (char *)c85);
709
	}
710
	Bprint(ioutb, "\n~>");
711
	Bprint(ioutb, "\n");
712
	freememimage(tmp);
713
}
714
 
715
int
716
image2psfile(int fd, Memimage *im, int dpi) {
717
	Rectangle r;
718
	Rectangle bbox;
719
	int e;
720
	int xmargin = 36;
721
	int ymargin = 36;
722
	double paperaspectratio;
723
	double imageaspectratio;
724
	Biobuf ioutb;
725
	Memimage *tmp;
726
 
727
	if(im->depth >= 8 && im->chan != CMAP8 && im->chan != GREY8){
728
		/*
729
		 * the postscript libraries can only handle [1248]-bit grey, 8-bit cmap,
730
		 * and 24-bit color, so convert.
731
		 */
732
		tmp = allocmemimage(im->r, strtochan("b8g8r8"));
733
		if(tmp == nil)
734
			return 1;
735
		memimagedraw(tmp, tmp->r, im, im->r.min, nil, ZP, S);
736
		freememimage(im);
737
		im = tmp;
738
	}
739
 
740
	Binit(&ioutb, fd, OWRITE);
741
 	r = im->r;
742
	width = Dx(r);
743
	height = Dy(r);
744
	imageaspectratio = (double) width / (double) height;
745
	if (landscape) {
746
		paperaspectratio = ((double)paperlength - (ymargin * 2)) / ((double)paperwidth - (xmargin * 2));
747
		if (dpi > 0) {
748
			iwidth = width * 72 / dpi;
749
			iheight = height * 72 / dpi;
750
		} else if (imageaspectratio > paperaspectratio) {
751
			iwidth = paperlength - (ymargin * 2);
752
			iheight = iwidth / imageaspectratio;
753
		} else {
754
			iheight = paperwidth - (xmargin * 2);
755
			iwidth  = iheight * imageaspectratio;
756
		}
757
		xstart = paperwidth - xmargin - (iheight * ymagnification);
758
		ystart = paperlength - ymargin;
759
		rotation = -90;
760
	} else {
761
		paperaspectratio = ((double)paperwidth - (xmargin * 2)) / ((double)paperlength - (ymargin * 2));
762
		if (dpi > 0) {
763
			iwidth = width * 72 / dpi;
764
			iheight = height * 72 / dpi;
765
		} else if (imageaspectratio > paperaspectratio) {
766
			iwidth = paperwidth - (xmargin * 2);
767
			iheight = iwidth / imageaspectratio;
768
		} else {
769
			iheight = paperlength - (ymargin * 2);
770
			iwidth  = iheight * imageaspectratio;
771
		}
772
		xstart = xmargin;
773
		ystart = paperlength - ymargin - (iheight * ymagnification);
774
		rotation = 0;
775
	}
776
	bbox = Rect(xstart,ystart,xstart+iwidth,ystart+iheight);
777
	e = preamble(&ioutb, bbox);
778
	if(e != 0)
779
		return e;
780
	Bprint(&ioutb, "%%%%Page: 1\n%%%%BeginPageSetup\n");
781
	Bprint(&ioutb, "/pgsave save def\n");
782
	Bprint(&ioutb, "%%%%EndPageSetup\n");
783
	bps = im->depth;
784
	Bprint(&ioutb, "%d 0 %d %d %d %d %d %d %s doimage\n", iheight, iwidth, ystart, xstart, height, width, bps, im->flags&Fgrey ? "true" : "false");
785
 	imagebits(&ioutb, im);
786
	Bprint(&ioutb, "pgsave restore\nshowpage\n");
787
	e = trailer(&ioutb, 1);
788
	if(e != 0)
789
		return e;
790
	Bterm(&ioutb);
791
	return 0;
792
}
793
 
794
/* set local variables by string and pointer to its value
795
 * the variables are:
796
 *   int magnification
797
 *   int landscape
798
 *   char *Patch
799
 */
800
void
801
psopt(char *s, void *val)
802
{
803
	if(s == nil)
804
		return;
805
	if(strcmp("xmagnification", s) == 0)
806
		xmagnification = *((double *)val);
807
	if(strcmp("ymagnification", s) == 0)
808
		ymagnification = *((double *)val);
809
	if(strcmp("landscape", s) == 0)
810
		landscape = *((int *)val);
811
	if(strcmp("Patch", s) == 0)
812
		Patch = *((char **)val);
813
}