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); 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", 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, 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 paperlength = 792; 721 int paperwidth = 612; 722 int xmargin = 36; 723 int ymargin = 36; 724 double paperaspectratio; 725 double imageaspectratio; 726 Biobuf ioutb; 727 Memimage *tmp; 728 729 if(im->depth >= 8 && im->chan != CMAP8 && im->chan != GREY8){ 730 /* 731 * the postscript libraries can only handle [1248]-bit grey, 8-bit cmap, 732 * and 24-bit color, so convert. 733 */ 734 tmp = allocmemimage(im->r, strtochan("b8g8r8")); 735 if(tmp == nil) 736 return 1; 737 memimagedraw(tmp, tmp->r, im, im->r.min, nil, ZP); 738 freememimage(im); 739 im = tmp; 740 } 741 742 Binit(&ioutb, fd, OWRITE); 743 r = im->r; 744 width = Dx(r); 745 height = Dy(r); 746 imageaspectratio = (double) width / (double) height; 747 if (landscape) { 748 paperaspectratio = ((double)paperlength - (ymargin * 2)) / ((double)paperwidth - (xmargin * 2)); 749 if (dpi > 0) { 750 iwidth = width * 72 / dpi; 751 iheight = height * 72 / dpi; 752 } else if (imageaspectratio > paperaspectratio) { 753 iwidth = paperlength - (ymargin * 2); 754 iheight = iwidth / imageaspectratio; 755 } else { 756 iheight = paperwidth - (xmargin * 2); 757 iwidth = iheight * imageaspectratio; 758 } 759 xstart = paperwidth - xmargin - (iheight * ymagnification); 760 ystart = paperlength - ymargin; 761 rotation = -90; 762 } else { 763 paperaspectratio = ((double)paperwidth - (xmargin * 2)) / ((double)paperlength - (ymargin * 2)); 764 if (dpi > 0) { 765 iwidth = width * 72 / dpi; 766 iheight = height * 72 / dpi; 767 } else if (imageaspectratio > paperaspectratio) { 768 iwidth = paperwidth - (xmargin * 2); 769 iheight = iwidth / imageaspectratio; 770 } else { 771 iheight = paperlength - (ymargin * 2); 772 iwidth = iheight * imageaspectratio; 773 } 774 xstart = xmargin; 775 ystart = paperlength - ymargin - (iheight * ymagnification); 776 rotation = 0; 777 } 778 bbox = Rect(xstart,ystart,xstart+iwidth,ystart+iheight); 779 e = preamble(&ioutb, bbox); 780 if(e != 0) 781 return e; 782 Bprint(&ioutb, "%%%%Page: 1\n%%%%BeginPageSetup\n"); 783 Bprint(&ioutb, "/pgsave save def\n"); 784 Bprint(&ioutb, "%%%%EndPageSetup\n"); 785 bps = im->depth; 786 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"); 787 imagebits(&ioutb, im); 788 Bprint(&ioutb, "pgsave restore\nshowpage\n"); 789 e = trailer(&ioutb, 1); 790 if(e != 0) 791 return e; 792 Bterm(&ioutb); 793 return 0; 794 } 795 796 /* set local variables by string and pointer to its value 797 * the variables are: 798 * int magnification 799 * int landscape 800 * char *Patch 801 */ 802 void 803 psopt(char *s, void *val) 804 { 805 if(s == nil) 806 return; 807 if(strcmp("xmagnification", s) == 0) 808 xmagnification = *((double *)val); 809 if(strcmp("ymagnification", s) == 0) 810 ymagnification = *((double *)val); 811 if(strcmp("landscape", s) == 0) 812 landscape = *((int *)val); 813 if(strcmp("Patch", s) == 0) 814 Patch = *((char **)val); 815 } 816