pslib.c 23 KB

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