PageRenderTime 61ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/src/Velvet/pslib.c

#
C | 745 lines | 622 code | 79 blank | 44 comment | 114 complexity | 9966b298b72b6886ddea430e76a937c2 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*
  2. * this code taken basically verbatim (changes and deletions only where
  3. * necessary) from the xmgr package by Paul J. Turner. It looks like he
  4. * got if from somewhere else too, so credit to those folks as well.
  5. */
  6. /*
  7. *
  8. * driver for postscript printer
  9. *
  10. * courtesy of:
  11. *
  12. * Jim Hudgens
  13. * hudgens@ray.met.fsu.edu
  14. *
  15. * Further modifications by,
  16. * Ole Holm Nielsen
  17. * ohnielse@ltf.dth.dk
  18. *
  19. */
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include "version.h"
  23. #define MAX_BUF_LEN 128
  24. static void putps();
  25. static int isoneof();
  26. static void stripspecial ();
  27. /* postscript page at scale = 0.25 */
  28. /*
  29. * the following defines are tuned for our HP LaserJet IV
  30. * and may need adjustment for other printers
  31. */
  32. #define PSXMIN 100
  33. #define PSXMAX 2350
  34. #define PSYMIN 100
  35. #define PSYMAX 3045
  36. #define DXPS 2250
  37. #define DYPS 2945
  38. #define CHARS 1.8
  39. #define MINCOLOR 0
  40. #define PSMAXPAT 30
  41. #define MAXLINEWIDTH 9
  42. static int psxmin = PSXMIN;
  43. static int psxmax = PSXMAX;
  44. static int psymin = PSYMIN;
  45. static int psymax = PSYMAX;
  46. static int psdx = DXPS;
  47. static int psdy = DYPS;
  48. static int pscolor = -1;
  49. static int pslinewidth = -1;
  50. static int psdmode;
  51. static int pspattern = 0;
  52. static int psfont = 0;
  53. static double pscharsize = 1.7;
  54. static int pslinestyle;
  55. static char *fname;
  56. /* reduced from 1000 to 800 PJT */
  57. #define MAXPATHLEN 800 /* MAXPATHLEN points in a path between
  58. * strokes */
  59. static int pathlength = 0;
  60. static FILE *psout;
  61. static int prevx = 99999,
  62. prevy = 99999,
  63. prevmode;
  64. static void stroke()
  65. {
  66. if (pathlength) {
  67. fprintf(psout, "stroke\n");
  68. prevx = 99999;
  69. prevy = 99999;
  70. pathlength = 0;
  71. }
  72. }
  73. int pssetmode(mode, ps_fp)
  74. int mode;
  75. FILE *ps_fp;
  76. {
  77. if (mode % 2) {
  78. psout = ps_fp;
  79. if (psout == NULL)
  80. return 0;
  81. }
  82. switch (mode) {
  83. case 3: /* EPS portrait */
  84. pscharsize = CHARS;
  85. psxmin = PSXMIN;
  86. psxmax = PSXMAX;
  87. psymin = PSYMIN;
  88. psymax = PSYMAX;
  89. psdx = DXPS;
  90. psdy = DYPS;
  91. break;
  92. case 1: /* EPS landscape */
  93. pscharsize = CHARS;
  94. psxmin = PSYMIN;
  95. psxmax = PSYMAX;
  96. psymin = PSXMIN;
  97. psymax = PSXMAX;
  98. psdx = DYPS;
  99. psdy = DXPS;
  100. break;
  101. case 2:
  102. case 4:
  103. stroke();
  104. fprintf(psout, "showpage\n");
  105. fprintf(psout, "%%%%Trailer\n");
  106. fclose(psout);
  107. break;
  108. }
  109. return mode;
  110. }
  111. void drawps(x2, y2, mode)
  112. int x2, y2, mode;
  113. {
  114. int xtmp, ytmp;
  115. if (x2 < 0 || y2 < 0) { /* Eliminate garbage on output */
  116. return;
  117. }
  118. xtmp = x2;
  119. ytmp = y2;
  120. if (mode) {
  121. if (prevmode && xtmp == prevx && ytmp == prevy) {
  122. return; /* previous mode was draw and points are the
  123. * same */
  124. }
  125. fprintf(psout, "%d %d l\n", xtmp, ytmp); /* lineto */
  126. } else {
  127. /* Avoid excessive moveto */
  128. if (xtmp == prevx && ytmp == prevy) {
  129. return;
  130. }
  131. fprintf(psout, "%d %d m\n", xtmp, ytmp); /* moveto */
  132. }
  133. pathlength++;
  134. prevx = xtmp;
  135. prevy = ytmp;
  136. /*
  137. * Printers have some maximum number of points in a path. See PostScript
  138. * Language Reference Manual (Red book), p. 261. Hence the fix that
  139. * follows
  140. */
  141. prevmode = mode;
  142. if (pathlength > MAXPATHLEN) {
  143. stroke();
  144. prevmode = 0;
  145. fprintf(psout, "%d %d m\n", xtmp, ytmp); /* moveto */
  146. }
  147. }
  148. int xconvps(x)
  149. double x;
  150. {
  151. return ((int) (psxmin + x));
  152. }
  153. int yconvps(y)
  154. double y;
  155. {
  156. return ((int) (psymin + y));
  157. }
  158. int pssetcolor(c)
  159. int c;
  160. {
  161. static int first_time = 1;
  162. static unsigned char red[16],
  163. green[16],
  164. blue[16];
  165. if (first_time) {
  166. first_time = 0;
  167. /* white */ red[0] = 255; green[0] = 255; blue[0] = 255;
  168. /* black */ red[1] = 0; green[1] = 0; blue[1] = 0;
  169. /* red */ red[2] = 255; green[2] = 0; blue[2] = 0;
  170. /* green */ red[3] = 0; green[3] = 255; blue[3] = 0;
  171. /* blue */ red[4] = 0; green[4] = 0; blue[4] = 255;
  172. /* yellow */ red[5] = 255; green[5] = 255; blue[5] = 0;
  173. /* brown */ red[6] = 188; green[6] = 143; blue[6] = 143;
  174. /* gray */ red[7] = 220; green[7] = 220; blue[7] = 220;
  175. /* violet */ red[8] = 148; green[8] = 0; blue[8] = 211;
  176. /* cyan */ red[9] = 0; green[9] = 255; blue[9] = 255;
  177. /* magenta*/ red[10] = 255; green[10] = 0; blue[10] = 211;
  178. /* orange */ red[11] = 255; green[11] = 138; blue[11] = 0;
  179. /* b violet*/ red[12] = 114; green[12] = 33; blue[12] = 188;
  180. /* maroon */ red[13] = 103; green[13] = 7; blue[13] = 72;
  181. /* turq */ red[14] = 72; green[14] = 209; blue[14] = 204;
  182. /* f green*/ red[15] = 85; green[15] = 192; blue[15] = 52;
  183. }
  184. stroke();
  185. if (c != pscolor) {
  186. if (c >= 0) {
  187. fprintf(psout, "%f %f %f setrgbcolor\n", red[c] / 255.0,
  188. green[c] / 255.0,
  189. blue[c] / 255.0);
  190. pscolor = 1;
  191. }
  192. }
  193. pscolor = c;
  194. return c;
  195. }
  196. int pssetlinewidth(c)
  197. int c;
  198. {
  199. stroke();
  200. if (c != pslinewidth) {
  201. c = c % (MAXLINEWIDTH + 1);
  202. if (c == 1)
  203. fprintf(psout, "1 setlinewidth\n");
  204. else
  205. fprintf(psout, "%d setlinewidth\n", (int) (3.5 * c + 0.51));
  206. }
  207. pslinewidth = c;
  208. return c;
  209. }
  210. int pssetlinestyle(style)
  211. int style;
  212. {
  213. stroke();
  214. if (style == pslinestyle) {
  215. return (pslinestyle);
  216. }
  217. switch (style) {
  218. case 1: /* solid */
  219. fprintf(psout, "[] 0 setdash\n");
  220. break;
  221. case 2: /* dotted */
  222. fprintf(psout, "[4 8] 0 setdash\n");
  223. break;
  224. case 3: /* long dash */
  225. fprintf(psout, "[20 20] 0 setdash\n");
  226. break;
  227. case 4: /* short dash */
  228. fprintf(psout, "[40 20] 0 setdash\n");
  229. break;
  230. case 5: /* dot-dashed */
  231. fprintf(psout, "[40 20 12 20] 0 setdash\n");
  232. break;
  233. }
  234. return (pslinestyle = style);
  235. }
  236. char pscurfont[MAX_BUF_LEN] = "/Times-Roman findfont \n60 scalefont\n setfont";
  237. int psfontsize = 60;
  238. void pssetfont(n)
  239. int n;
  240. {
  241. if (psfont == n) {
  242. return;
  243. }
  244. switch (n) {
  245. case 0:
  246. sprintf(pscurfont, "/Times-Roman findfont \n%d scalefont\n setfont", psfontsize);
  247. break;
  248. case 1:
  249. sprintf(pscurfont, "/Times-Bold findfont \n%d scalefont\n setfont", psfontsize);
  250. break;
  251. case 2:
  252. sprintf(pscurfont, "/Times-Italic findfont \n%d scalefont\n setfont", psfontsize);
  253. break;
  254. case 3:
  255. sprintf(pscurfont, "/Times-BoldItalic findfont \n%d scalefont\n setfont", psfontsize);
  256. break;
  257. case 4:
  258. sprintf(pscurfont, "/Helvetica findfont \n%d scalefont\n setfont", psfontsize);
  259. break;
  260. case 5:
  261. sprintf(pscurfont, "/Helvetica-Bold findfont \n%d scalefont\n setfont", psfontsize);
  262. break;
  263. case 6:
  264. sprintf(pscurfont, "/Helvetica-Oblique findfont \n%d scalefont\n setfont", psfontsize);
  265. break;
  266. case 7:
  267. sprintf(pscurfont, "/Helvetica-BoldOblique findfont \n%d scalefont\n setfont", psfontsize);
  268. break;
  269. case 8:
  270. sprintf(pscurfont, "/Courier findfont \n%d scalefont\n setfont", psfontsize);
  271. break;
  272. case 9:
  273. sprintf(pscurfont, "/Courier-Bold findfont \n%d scalefont\n setfont", psfontsize);
  274. break;
  275. case 10:
  276. sprintf(pscurfont, "/Courier-Oblique findfont \n%d scalefont\n setfont", psfontsize);
  277. break;
  278. case 11:
  279. sprintf(pscurfont, "/Courier-BoldOblique findfont \n%d scalefont\n setfont", psfontsize);
  280. break;
  281. case 12:
  282. sprintf(pscurfont, "/Symbol findfont \n%d scalefont\n setfont", psfontsize);
  283. break;
  284. case 13:
  285. sprintf(pscurfont, "/Symbol findfont \n%d scalefont\n setfont", psfontsize);
  286. break;
  287. case 14:
  288. sprintf(pscurfont, "/Symbol findfont \n%d scalefont\n setfont", psfontsize);
  289. break;
  290. }
  291. fprintf(psout, "%s\n", pscurfont);
  292. psfont = n;
  293. }
  294. void pssetfontsize(size)
  295. double size;
  296. {
  297. static double prev_size;
  298. int sf = psfont;
  299. if (size == prev_size)
  300. return;
  301. psfontsize = (int) (size * 4); /* to account for the 0.25 scaling */
  302. psfont = -1;
  303. pssetfont(sf);
  304. }
  305. static void escape_paren(s)
  306. char *s;
  307. {
  308. char t[256];
  309. int i, cnt = 0;
  310. for (i = 0; i < strlen(s); i++) {
  311. if (s[i] == '(' || s[i] == ')') {
  312. t[cnt++] = '\\';
  313. }
  314. t[cnt++] = s[i];
  315. }
  316. t[cnt] = 0;
  317. strcpy(s, t);
  318. }
  319. void dispstrps(x, y, rot, s, just, fudge)
  320. int x, y, rot, just, fudge;
  321. char *s;
  322. {
  323. char tmpstr[256];
  324. stroke();
  325. if (psfontsize == 0 || s == NULL || strlen(s) == 0) {
  326. return;
  327. }
  328. fprintf(psout, "%d %d m\n", x, y);
  329. fprintf(psout, "gsave\n");
  330. fprintf(psout, "%d %d translate\n", x, y);
  331. fprintf(psout, "%d rotate\n", rot);
  332. if (fudge) {
  333. fprintf(psout, "%d 0 m\n", psfontsize / 4);
  334. } else {
  335. fprintf(psout, "0 0 m\n");
  336. }
  337. switch (just) {
  338. case 0:
  339. break;
  340. case 1:
  341. stripspecial(s, tmpstr);
  342. escape_paren(tmpstr);
  343. fprintf(psout, "(%s) RJ\n", tmpstr);
  344. break;
  345. case 2:
  346. stripspecial(s, tmpstr);
  347. escape_paren(tmpstr);
  348. fprintf(psout, "(%s) CS\n", tmpstr);
  349. break;
  350. }
  351. putps(s);
  352. fprintf(psout, "grestore\n");
  353. fprintf(psout, "newpath\n");
  354. }
  355. static void putps(s)
  356. char *s;
  357. {
  358. int i, slen = strlen(s), curcnt = 0;
  359. int underline = 0, offset = 0;
  360. double saves = psfontsize / 60.0, scale = psfontsize / 60.0;
  361. char curstr[256];
  362. int upperset = 0;
  363. int symfont = 0;
  364. if (psfont == 9) {
  365. symfont = 1;
  366. upperset = 0x80;
  367. } else {
  368. symfont = 0;
  369. upperset = 0;
  370. }
  371. for (i = 0; i < slen; i++) {
  372. if (s[i] == '-' && isdigit(s[i + 1])) {
  373. /* s[i] = 0261; */
  374. } else if (s[i] == '\\' && isdigit(s[i + 1])) {
  375. curstr[curcnt] = 0;
  376. if (curcnt >= 1) {
  377. fprintf(psout, "(%s) show\n", curstr);
  378. }
  379. curcnt = 0;
  380. if (symfont) {
  381. symfont = 0;
  382. upperset = 0;
  383. }
  384. pssetfont(s[i + 1] - '0');
  385. if (psfont == 9) {
  386. symfont = 1;
  387. upperset = 0x80;
  388. }
  389. i++;
  390. continue;
  391. } else if (s[i] == '(' || s[i] == ')') {
  392. curstr[curcnt++] = '\\';
  393. } else if (s[i] == '\\' && isoneof(s[i + 1], "cCbxsSNuU+-")) {
  394. switch (s[i + 1]) {
  395. case 'x':
  396. curstr[curcnt] = 0;
  397. if (curcnt >= 1) {
  398. fprintf(psout, "(%s) show\n", curstr);
  399. }
  400. curcnt = 0;
  401. if (symfont == 0) {
  402. symfont = 1;
  403. upperset = 0x80;
  404. }
  405. pssetfont(10);
  406. i++;
  407. break;
  408. case 's':
  409. curstr[curcnt] = 0;
  410. if (curcnt >= 1) {
  411. fprintf(psout, "(%s) show\n", curstr);
  412. }
  413. curcnt = 0;
  414. pssetfontsize(scale = 0.6 * saves);
  415. offset -= psfontsize / 2;
  416. fprintf(psout, "0 %d rmoveto\n", -(psfontsize / 2));
  417. i++;
  418. break;
  419. case 'S':
  420. curstr[curcnt] = 0;
  421. if (curcnt >= 1) {
  422. fprintf(psout, "(%s) show\n", curstr);
  423. }
  424. curcnt = 0;
  425. pssetfontsize(scale = 0.6 * saves);
  426. offset += psfontsize;
  427. fprintf(psout, "0 %d rmoveto\n", psfontsize);
  428. i++;
  429. break;
  430. case 'N':
  431. curstr[curcnt] = 0;
  432. if (curcnt >= 1) {
  433. fprintf(psout, "(%s) show\n", curstr);
  434. }
  435. curcnt = 0;
  436. scale = saves;
  437. pssetfontsize(scale);
  438. fprintf(psout, "0 %d rmoveto\n", -offset);
  439. offset = 0;
  440. /*
  441. fprintf(psout, "0 %d rmoveto\n", psfontsize);
  442. */
  443. i++;
  444. break;
  445. case 'b':
  446. i++;
  447. break;
  448. case 'c':
  449. upperset = 0x80;
  450. i++;
  451. break;
  452. case 'C':
  453. upperset = 0;
  454. i++;
  455. break;
  456. case 'u':
  457. underline = 1;
  458. i++;
  459. break;
  460. case 'U':
  461. underline = 0;
  462. i++;
  463. break;
  464. case '-':
  465. curstr[curcnt] = 0;
  466. if (curcnt >= 1) {
  467. fprintf(psout, "(%s) show\n", curstr);
  468. }
  469. curcnt = 0;
  470. scale -= 0.2;
  471. if (scale < 0.2) {
  472. scale = 0.2;
  473. }
  474. pssetfontsize(scale);
  475. i++;
  476. break;
  477. case '+':
  478. curstr[curcnt] = 0;
  479. if (curcnt >= 1) {
  480. fprintf(psout, "(%s) show\n", curstr);
  481. }
  482. curcnt = 0;
  483. scale += 0.2;
  484. pssetfontsize(scale);
  485. i++;
  486. break;
  487. }
  488. continue;
  489. } else if (s[i] == '\\' && s[i + 1] == '\\') {
  490. curstr[curcnt++] = '\\';
  491. curstr[curcnt++] = s[i];
  492. i++;
  493. continue;
  494. }
  495. curstr[curcnt++] = s[i] + upperset;
  496. }
  497. curstr[curcnt] = 0;
  498. fprintf(psout, "(%s) show\n", curstr);
  499. }
  500. int pssetpat(k)
  501. int k;
  502. {
  503. stroke();
  504. if (k > PSMAXPAT) {
  505. k = PSMAXPAT;
  506. } else if (k < 0) {
  507. k = 0;
  508. fprintf(psout, "0.0 setgray\n");
  509. }
  510. return (pspattern = k);
  511. }
  512. void psfill(n, px, py)
  513. int n;
  514. int px[], py[];
  515. {
  516. int i;
  517. stroke();
  518. drawps(px[0], py[0], 0);
  519. for (i = 1; i < n; i++) {
  520. drawps(px[i], py[i], 1);
  521. }
  522. fprintf(psout, "closepath\n");
  523. fprintf(psout, "%f setgray\n", 1.0 - pspattern / (double) PSMAXPAT);
  524. fprintf(psout, "gsave eofill grestore\n");
  525. stroke();
  526. fprintf(psout, "0 setgray\n");
  527. }
  528. void psfillcolor(n, px, py)
  529. int n;
  530. int px[], py[];
  531. {
  532. int i;
  533. stroke();
  534. drawps(px[0], py[0], 0);
  535. for (i = 1; i < n; i++) {
  536. drawps(px[i], py[i], 1);
  537. }
  538. fprintf(psout, "closepath\n");
  539. fprintf(psout, "gsave eofill grestore\n");
  540. stroke();
  541. }
  542. void psdrawarc(x, y, r, start, end)
  543. int x, y, r, start, end;
  544. {
  545. stroke();
  546. fprintf(psout, "%d %d %d %d %d arc\n", x, y, r, start, end);
  547. fprintf(psout, "stroke\n");
  548. }
  549. void psfillarc(x, y, r, start, end)
  550. int x, y, r, start, end;
  551. {
  552. stroke();
  553. fprintf(psout, "%d %d %d %d %d arc\n", x, y, r, start, end);
  554. fprintf(psout, "gsave fill grestore\n");
  555. fprintf(psout, "stroke\n");
  556. }
  557. void psdrawellipse(x, y, xm, ym, start, end)
  558. int x, y, xm, ym, start, end;
  559. {
  560. double scalex = (double) xm / (double) ym, scaley = 1.0;
  561. stroke();
  562. fprintf(psout, "gsave\n");
  563. fprintf(psout, "%f %f scale\n", scalex, scaley);
  564. fprintf(psout, "%d %d %d %d %d arc\n", (int) (x * 1.0 / scalex),
  565. y, ym, start, end);
  566. fprintf(psout, "stroke\n");
  567. fprintf(psout, "grestore\n");
  568. }
  569. void psfillellipse(x, y, xm, ym, start, end)
  570. int x, y, xm, ym, start, end;
  571. {
  572. double scalex = (double) xm / (double) ym, scaley = 1.0;
  573. stroke();
  574. fprintf(psout, "gsave\n");
  575. fprintf(psout, "%f %f scale\n", scalex, scaley);
  576. /*
  577. fprintf(psout, "%d %d %d %d %d arc\n", x, y, ym, start, end);
  578. */
  579. fprintf(psout, "%d %d %d %d %d arc\n", (int) (x * 1.0 / scalex),
  580. y, ym, start, end);
  581. fprintf(psout, "gsave fill grestore\n");
  582. fprintf(psout, "stroke\n");
  583. fprintf(psout, "grestore\n");
  584. }
  585. int psgetextents (x, y)
  586. int *x, *y;
  587. {
  588. *x = psdx;
  589. *y = psdy;
  590. return 0;
  591. }
  592. void psleavegraphics(fp)
  593. FILE *fp;
  594. {
  595. pssetmode(psdmode + 1, fp);
  596. }
  597. /* postscript initialization routine */
  598. int psinitgraphics(dmode, ps_fp)
  599. int dmode;
  600. FILE *ps_fp;
  601. {
  602. psdmode = dmode;
  603. if (!pssetmode(psdmode, ps_fp)) {
  604. return -1;
  605. }
  606. fprintf(psout, "%%!PostScript\n");
  607. fprintf(psout, "%%%%Creator: Velvet %s\n", VERSION);
  608. fprintf(psout, "%%%%Title: %s\n", fname);
  609. fprintf(psout, "%%%%EndComments\n");
  610. fprintf(psout, "/m {moveto} bind def\n");
  611. fprintf(psout, "/l {lineto} bind def\n");
  612. fprintf(psout, "/RJ {\n");
  613. fprintf(psout, " stringwidth neg exch neg exch\n");
  614. fprintf(psout, " rmoveto\n");
  615. fprintf(psout, "} bind def\n");
  616. fprintf(psout, "/CS {\n");
  617. fprintf(psout, " stringwidth\n");
  618. fprintf(psout, " 2 div neg exch 2 div neg exch\n");
  619. fprintf(psout, " rmoveto\n");
  620. fprintf(psout, "} bind def\n");
  621. fprintf(psout, "0.25 0.25 scale\n");
  622. fprintf(psout, "1 setlinecap\n");
  623. /*
  624. * rotate if in landscape mode
  625. */
  626. if (dmode == 1) {
  627. fprintf(psout, "%d 0 translate\n", 2 * psymin + psdy);
  628. fprintf(psout, "90 rotate\n");
  629. }
  630. pssetcolor(1);
  631. pssetlinewidth(1);
  632. pssetlinestyle(0);
  633. psfont = -1;
  634. pssetfont(2);
  635. return 0;
  636. }
  637. static int isoneof(c, s)
  638. int c;
  639. char *s;
  640. {
  641. while (*s) {
  642. if (c == *s) {
  643. return 1;
  644. } else {
  645. s++;
  646. }
  647. }
  648. return 0;
  649. }
  650. static void stripspecial(s, cs)
  651. char *s, *cs;
  652. {
  653. int i, slen = strlen(s), curcnt = 0;
  654. for (i = 0; i < slen; i++) {
  655. if (s[i] == '\\' && isdigit(s[i + 1])) {
  656. i++;
  657. } else if (s[i] == '\\' && isoneof(s[i + 1], "cCbxsSNuU+-")) {
  658. i++;
  659. } else if (s[i] == '\\' && s[i + 1] == '\\') {
  660. i++;
  661. } else {
  662. cs[curcnt++] = s[i];
  663. }
  664. }
  665. cs[curcnt] = 0;
  666. }