PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/branches/tea/bindings/tk/plr.c

#
C | 560 lines | 308 code | 109 blank | 143 comment | 36 complexity | 8ef8e1e2ef671a4dcdf550074dffe233 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, Apache-2.0, GPL-2.0
  1. /* $Id: plr.c 1846 1995-09-22 16:04:16Z mjl $
  2. * $Log$
  3. * Revision 1.20 1995/09/22 16:04:12 mjl
  4. * Fixes to names of member variables of PLiodev structs.
  5. *
  6. * Revision 1.19 1995/03/16 23:08:06 mjl
  7. * The Copyright message was changed and general cleaning up done.
  8. *
  9. * Revision 1.18 1994/08/25 03:59:43 mjl
  10. * Fixed to properly update driver when cmap state is changed. Contributed
  11. * by Radey Shouman.
  12. *
  13. * Revision 1.17 1994/07/18 20:29:58 mjl
  14. * Fixed the escape function to pass ALL received escape commands.
  15. *
  16. * Revision 1.16 1994/06/30 18:43:02 mjl
  17. * Cleaning up to remove gcc -Wall warnings, and other miscellanea.
  18. */
  19. /*
  20. plr.c
  21. Copyright 1993, 1994, 1995
  22. Maurice LeBrun
  23. IFS, University of Texas at Austin
  24. This software may be freely copied, modified and redistributed under the
  25. terms of the GNU Library General Public License.
  26. There is no warranty or other guarantee of fitness of this software.
  27. It is provided solely "as is". The author(s) disclaim(s) all
  28. responsibility and liability with respect to this software's usage or
  29. its effect upon hardware or computer systems.
  30. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  31. *
  32. * Support routines to render a PLplot byte stream, interpreting the PLplot
  33. * metacode.
  34. *
  35. * Although this code is duplicated to some extent by plrender and the
  36. * plot buffer redraw code (in plbuf.c), they are all different in some
  37. * significant ways, namely:
  38. *
  39. * - plrender must always retain backward compatibility code to
  40. * handle old metafiles, as well as stuff to support seeking.
  41. *
  42. * - plbuf by definition is redrawing on the same machine so no
  43. * special effort is necessary to make the byte stream portable,
  44. * also, only low-level graphics calls are used (grline, etc)
  45. *
  46. * The rendering code here must (by contrast to plbuf) use the high level
  47. * plot routines (as does plrender), to support local zooms as well as the
  48. * ability to dump the associated window into plot space to a file, but is
  49. * otherwise pretty minimal. A portable byte stream is used since network
  50. * communication over a socket may be used.
  51. *
  52. \*--------------------------------------------------------------------------*/
  53. /*
  54. #define DEBUG
  55. #define DEBUG_ENTER
  56. */
  57. #include "plserver.h"
  58. #include "plevent.h"
  59. #include "metadefs.h"
  60. /* Some wrapper macros to return (-1) on error */
  61. #define plr_rd(code) \
  62. if (code) { fprintf(stderr, \
  63. "Unable to read from %s in %s at line %d, bytecount %ld\n", \
  64. plr->iodev->typeName, __FILE__, __LINE__, plr->pdfs->bp); \
  65. return -1; }
  66. #define plr_cmd(code) \
  67. if ((code) == -1) return -1;
  68. /* Error termination */
  69. #define barf(msg) \
  70. { fprintf(stderr, "%s\nCommand code: %d, byte count: %ld\n", \
  71. msg, csave, plr->pdfs->bp); return -1; }
  72. /* Static function prototypes. */
  73. static int plr_process1 (PLRDev *plr, int c);
  74. static int plr_init (PLRDev *plr);
  75. static int plr_line (PLRDev *plr, int c);
  76. static int plr_eop (PLRDev *plr);
  77. static int plr_bop (PLRDev *plr);
  78. static int plr_state (PLRDev *plr);
  79. static int plr_esc (PLRDev *plr);
  80. static int plr_get (PLRDev *plr);
  81. static int plr_unget (PLRDev *plr, U_CHAR c);
  82. static int get_ncoords (PLRDev *plr, PLFLT *x, PLFLT *y, PLINT n);
  83. static int plresc_fill (PLRDev *plr);
  84. /* variables */
  85. static int csave = -1;
  86. static U_CHAR dum_uchar;
  87. static U_SHORT dum_ushort;
  88. static PLFLT x[PL_MAXPOLY], y[PL_MAXPOLY];
  89. /*--------------------------------------------------------------------------*\
  90. * plr_start()
  91. *
  92. * Set default state parameters before anyone else has a chance to.
  93. \*--------------------------------------------------------------------------*/
  94. void
  95. plr_start(PLRDev *plr)
  96. {
  97. dbug_enter("plr_start");
  98. plr->xmin = 0;
  99. plr->xmax = PIXELS_X - 1;
  100. plr->ymin = 0;
  101. plr->ymax = PIXELS_Y - 1;
  102. plr->xold = UNDEFINED;
  103. plr->yold = UNDEFINED;
  104. }
  105. /*--------------------------------------------------------------------------*\
  106. * plr_process()
  107. *
  108. * Read & process commands until plr->nbytes bytes have been read.
  109. \*--------------------------------------------------------------------------*/
  110. int
  111. plr_process(PLRDev *plr)
  112. {
  113. int c;
  114. dbug_enter("plr_process");
  115. while (plr->pdfs->bp < plr->nbytes) {
  116. plr_cmd( c = plr_get(plr) );
  117. csave = c;
  118. plr_cmd( plr_process1(plr, c) );
  119. }
  120. return 0;
  121. }
  122. /*--------------------------------------------------------------------------*\
  123. * plr_process1()
  124. *
  125. * Process a command. Note: because of line->polyline compression, this
  126. * may actually process an arbitrary number of LINE or LINETO commands.
  127. * Since the data buffer (fifo or socket) is only flushed after a complete
  128. * command, there should be no danger in rushing blindly ahead to execute
  129. * each plot command.
  130. \*--------------------------------------------------------------------------*/
  131. static int
  132. plr_process1(PLRDev *plr, int c)
  133. {
  134. switch (c) {
  135. case INITIALIZE:
  136. plr_cmd( plr_init(plr) );
  137. break;
  138. case LINE:
  139. case LINETO:
  140. case POLYLINE:
  141. plr_cmd( plr_line(plr, c) );
  142. break;
  143. case EOP:
  144. plr->at_eop = 1;
  145. plr_cmd( plr_eop(plr) );
  146. break;
  147. case BOP:
  148. plr->at_bop = 1;
  149. plr_cmd( plr_bop(plr) );
  150. break;
  151. case CHANGE_STATE:
  152. plr_cmd( plr_state(plr) );
  153. break;
  154. case ESCAPE:
  155. plr_cmd( plr_esc(plr) );
  156. break;
  157. default:
  158. fprintf(stderr, "plr_process1: Unrecognized command code %d\n", c);
  159. }
  160. return 0;
  161. }
  162. /*--------------------------------------------------------------------------*\
  163. * void plr_init()
  164. *
  165. * Handle initialization.
  166. \*--------------------------------------------------------------------------*/
  167. static int
  168. plr_init(PLRDev *plr)
  169. {
  170. char tk_magic[80], tk_version[80], tag[80];
  171. dbug_enter("plr_init");
  172. /* Read header info */
  173. plr_cmd( pdf_rd_header(plr->pdfs, tk_magic) );
  174. if (strcmp(tk_magic, PLSERV_HEADER))
  175. barf("plr_init: Invalid header");
  176. /* Read version field of header. We need to check that we can read the */
  177. /* byte stream, in case this is an old version of plserver. */
  178. plr_cmd( pdf_rd_header(plr->pdfs, tk_version) );
  179. if (strcmp(tk_version, PLSERV_VERSION) > 0) {
  180. fprintf(stderr,
  181. "Error: incapable of reading output of version %s.\n", tk_version);
  182. barf("plr_init: Please obtain a newer copy of plserver.");
  183. }
  184. /* Read tagged initialization info. */
  185. /* Overkill, but a no-brainer since plrender already uses this */
  186. for (;;) {
  187. plr_cmd( pdf_rd_header(plr->pdfs, tag) );
  188. if (*tag == '\0')
  189. break;
  190. if ( ! strcmp(tag, "xmin")) {
  191. plr_rd( pdf_rd_2bytes(plr->pdfs, &dum_ushort) );
  192. plr->xmin = dum_ushort;
  193. continue;
  194. }
  195. if ( ! strcmp(tag, "xmax")) {
  196. plr_rd( pdf_rd_2bytes(plr->pdfs, &dum_ushort) );
  197. plr->xmax = dum_ushort;
  198. continue;
  199. }
  200. if ( ! strcmp(tag, "ymin")) {
  201. plr_rd( pdf_rd_2bytes(plr->pdfs, &dum_ushort) );
  202. plr->ymin = dum_ushort;
  203. continue;
  204. }
  205. if ( ! strcmp(tag, "ymax")) {
  206. plr_rd( pdf_rd_2bytes(plr->pdfs, &dum_ushort) );
  207. plr->ymax = dum_ushort;
  208. continue;
  209. }
  210. if ( ! strcmp(tag, "width")) {
  211. plr_rd( pdf_rd_1byte(plr->pdfs, &dum_uchar) );
  212. plwid(dum_uchar);
  213. continue;
  214. }
  215. barf("plr_init: Unrecognized initialization tag.");
  216. }
  217. return 0;
  218. }
  219. /*--------------------------------------------------------------------------*\
  220. * plr_line()
  221. *
  222. * Draw a line or polyline.
  223. \*--------------------------------------------------------------------------*/
  224. static int
  225. plr_line(PLRDev *plr, int c)
  226. {
  227. int c1;
  228. U_SHORT npts;
  229. npts = 1;
  230. x[0] = plr->xold;
  231. y[0] = plr->yold;
  232. switch ((int) c) {
  233. case LINE:
  234. plr_cmd( get_ncoords(plr, x, y, 1) );
  235. case LINETO:
  236. for (;;) {
  237. plr_cmd( get_ncoords(plr, x + npts, y + npts, 1) );
  238. npts++;
  239. if (npts == PL_MAXPOLY || (plr->pdfs->bp == plr->nbytes))
  240. break;
  241. plr_cmd( c1 = plr_get(plr) );
  242. if (c1 != LINETO) {
  243. plr_cmd( plr_unget(plr, (U_CHAR) c1) );
  244. break;
  245. }
  246. }
  247. break;
  248. case POLYLINE:
  249. plr_rd( pdf_rd_2bytes(plr->pdfs, &npts) );
  250. plr_cmd( get_ncoords(plr, x, y, npts) );
  251. break;
  252. }
  253. plline(npts, x, y);
  254. plr->xold = x[npts - 1];
  255. plr->yold = y[npts - 1];
  256. return 0;
  257. }
  258. /*--------------------------------------------------------------------------*\
  259. * get_ncoords()
  260. *
  261. * Read n coordinate vectors.
  262. \*--------------------------------------------------------------------------*/
  263. #define plr_rdn(code) \
  264. if (code) { fprintf(stderr, \
  265. "Unable to read from %s in %s at line %d, bytecount %d\n\
  266. Bytes requested: %d\n", plr->iodev->typeName, __FILE__, __LINE__, \
  267. (int) plr->pdfs->bp, (int) 2*n); return -1; }
  268. static int
  269. get_ncoords(PLRDev *plr, PLFLT *x, PLFLT *y, PLINT n)
  270. {
  271. int i;
  272. short xs[PL_MAXPOLY], ys[PL_MAXPOLY];
  273. plr_rdn( pdf_rd_2nbytes(plr->pdfs, (U_SHORT *) xs, n) );
  274. plr_rdn( pdf_rd_2nbytes(plr->pdfs, (U_SHORT *) ys, n) );
  275. for (i = 0; i < n; i++) {
  276. x[i] = xs[i];
  277. y[i] = ys[i];
  278. }
  279. return 0;
  280. }
  281. /*--------------------------------------------------------------------------*\
  282. * plr_eop()
  283. *
  284. * Clear screen.
  285. \*--------------------------------------------------------------------------*/
  286. static int
  287. plr_eop(PLRDev *plr)
  288. {
  289. dbug_enter("plr_eop");
  290. pleop();
  291. return 0;
  292. }
  293. /*--------------------------------------------------------------------------*\
  294. * plr_bop()
  295. *
  296. * Page advancement.
  297. \*--------------------------------------------------------------------------*/
  298. static int
  299. plr_bop(PLRDev *plr)
  300. {
  301. dbug_enter("plr_bop");
  302. /* Advance and setup the page */
  303. plbop();
  304. plvpor(0., 1., 0., 1.);
  305. plwind(plr->xmin, plr->xmax, plr->ymin, plr->ymax);
  306. return 0;
  307. }
  308. /*--------------------------------------------------------------------------*\
  309. * plr_state()
  310. *
  311. * Handle change in PLStream state (color, pen width, fill attribute,
  312. * etc).
  313. \*--------------------------------------------------------------------------*/
  314. static int
  315. plr_state(PLRDev *plr)
  316. {
  317. U_CHAR op;
  318. int i;
  319. plr_rd( pdf_rd_1byte(plr->pdfs, &op) );
  320. switch (op) {
  321. case PLSTATE_WIDTH:{
  322. U_SHORT width;
  323. plr_rd( pdf_rd_2bytes(plr->pdfs, &width) );
  324. plwid(width);
  325. break;
  326. }
  327. case PLSTATE_COLOR0:{
  328. U_CHAR icol0, r, g, b;
  329. plr_rd( pdf_rd_1byte(plr->pdfs, &icol0) );
  330. if (icol0 == PL_RGB_COLOR) {
  331. plr_rd( pdf_rd_1byte(plr->pdfs, &r) );
  332. plr_rd( pdf_rd_1byte(plr->pdfs, &g) );
  333. plr_rd( pdf_rd_1byte(plr->pdfs, &b) );
  334. plrgb1(r, g, b);
  335. }
  336. else {
  337. plcol(icol0);
  338. }
  339. break;
  340. }
  341. case PLSTATE_COLOR1:{
  342. U_SHORT icol1;
  343. PLFLT col1;
  344. plr_rd( pdf_rd_2bytes(plr->pdfs, &icol1) );
  345. col1 = (double) icol1 / (double) plsc->ncol1;
  346. plcol1(col1);
  347. break;
  348. }
  349. case PLSTATE_FILL:{
  350. signed char patt;
  351. plr_rd( pdf_rd_1byte(plr->pdfs, (U_CHAR *) &patt) );
  352. plpsty(patt);
  353. break;
  354. }
  355. case PLSTATE_CMAP0:{
  356. U_CHAR ncol0;
  357. plr_rd( pdf_rd_1byte(plr->pdfs, &ncol0) );
  358. plsc->ncol0 = ncol0;
  359. for (i = 0; i < plsc->ncol0; i++) {
  360. plr_rd( pdf_rd_1byte(plr->pdfs, &plsc->cmap0[i].r) );
  361. plr_rd( pdf_rd_1byte(plr->pdfs, &plsc->cmap0[i].g) );
  362. plr_rd( pdf_rd_1byte(plr->pdfs, &plsc->cmap0[i].b) );
  363. }
  364. plP_state(PLSTATE_CMAP0);
  365. break;
  366. }
  367. case PLSTATE_CMAP1:{
  368. U_SHORT ncol1;
  369. plr_rd( pdf_rd_2bytes(plr->pdfs, &ncol1) );
  370. plsc->ncol1 = ncol1;
  371. for (i = 0; i < plsc->ncol1; i++) {
  372. plr_rd( pdf_rd_1byte(plr->pdfs, &plsc->cmap1[i].r) );
  373. plr_rd( pdf_rd_1byte(plr->pdfs, &plsc->cmap1[i].g) );
  374. plr_rd( pdf_rd_1byte(plr->pdfs, &plsc->cmap1[i].b) );
  375. }
  376. plP_state(PLSTATE_CMAP1);
  377. break;
  378. }
  379. }
  380. return 0;
  381. }
  382. /*--------------------------------------------------------------------------*\
  383. * plr_esc()
  384. *
  385. * Handle all escape functions.
  386. * Only those that require additional data to be read need to be
  387. * explicitly handled; the others are merely passed on to the actual
  388. * driver.
  389. \*--------------------------------------------------------------------------*/
  390. static int
  391. plr_esc(PLRDev *plr)
  392. {
  393. U_CHAR op;
  394. plr_rd( pdf_rd_1byte(plr->pdfs, &op) );
  395. switch (op) {
  396. case PLESC_FILL:
  397. plr_cmd( plresc_fill(plr) );
  398. break;
  399. default:
  400. pl_cmd((PLINT) op, NULL);
  401. break;
  402. }
  403. return 0;
  404. }
  405. /*--------------------------------------------------------------------------*\
  406. * plresc_fill()
  407. *
  408. * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
  409. \*--------------------------------------------------------------------------*/
  410. static int
  411. plresc_fill(PLRDev *plr)
  412. {
  413. U_SHORT npts;
  414. dbug_enter("plresc_fill");
  415. plr_rd( pdf_rd_2bytes(plr->pdfs, &npts) );
  416. get_ncoords(plr, x, y, npts);
  417. plfill(npts, x, y);
  418. return 0;
  419. }
  420. /*--------------------------------------------------------------------------*\
  421. * plr_get()
  422. *
  423. * Read & return the next command
  424. \*--------------------------------------------------------------------------*/
  425. static int
  426. plr_get(PLRDev *plr)
  427. {
  428. int c;
  429. c = pdf_getc(plr->pdfs);
  430. if (c == EOF) {
  431. barf("plr_get: Unable to read character");
  432. }
  433. return c;
  434. }
  435. /*--------------------------------------------------------------------------*\
  436. * plr_unget()
  437. *
  438. * Push back the last command read.
  439. \*--------------------------------------------------------------------------*/
  440. static int
  441. plr_unget(PLRDev *plr, U_CHAR c)
  442. {
  443. if (pdf_ungetc(c, plr->pdfs) == EOF) {
  444. barf("plr_unget: Unable to push back character");
  445. }
  446. return 0;
  447. }