home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / maths / plplot / plplot_2 / drivers / plbuf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-23  |  16.0 KB  |  653 lines

  1. /* $Id: plbuf.c,v 1.18 1994/03/23 06:39:20 mjl Exp $
  2.  * $Log: plbuf.c,v $
  3.  * Revision 1.18  1994/03/23  06:39:20  mjl
  4.  * Added support for: color map 1 color selection, color map 0 or color map 1
  5.  * state change (palette change), polygon fills.
  6.  *
  7.  * All drivers: cleaned up by eliminating extraneous includes (stdio.h and
  8.  * stdlib.h now included automatically by plplotP.h), extraneous clears
  9.  * of pls->fileset, pls->page, and pls->OutFile = NULL (now handled in
  10.  * driver interface or driver initialization as appropriate).  Special
  11.  * handling for malloc includes eliminated (no longer needed) and malloc
  12.  * prototypes fixed as necessary.
  13.  *
  14.  * Revision 1.17  1994/01/15  17:19:13  mjl
  15.  * Eliminated include of pdf.h (not needed).
  16.  *
  17.  * Revision 1.16  1993/09/28  21:25:08  mjl
  18.  * Now discards the old temp file and opens a new one on each new page.  This
  19.  * avoids a lot of problems redisplaying partially filled pages -- we can
  20.  * just read to EOF without worrying about junk in the file from previous
  21.  * writes.  The old method never did work perfectly.
  22.  *
  23.  * Revision 1.15  1993/09/27  20:33:51  mjl
  24.  * Insignificant change to eliminate a gcc -Wall warning.
  25.  *
  26.  * Revision 1.14  1993/09/08  02:27:11  mjl
  27.  * Inserted change to ensure that streams that do not own the plot buffer
  28.  * cannot write to it (was causing problems on plot saves).
  29.  *
  30.  * Revision 1.13  1993/08/30  19:11:51  mjl
  31.  * Fixed the damage incurred by my previous "fix".  Plot buffer now appears
  32.  * capable of accurately and unobtrusively replaying partially filled pages.
  33.  *
  34.  * Revision 1.12  1993/08/28  06:28:07  mjl
  35.  * Fixed escape function reads & writes to be consistent.  Added plbuf_rewind
  36.  * function, which writes EOP's to the end of file to make sure that dicking
  37.  * around with the window settings before the page is complete doesn't end in
  38.  * a core dump.
  39.  *
  40.  * Revision 1.11  1993/07/31  07:56:40  mjl
  41.  * Several driver functions consolidated, for all drivers.  The width and color
  42.  * commands are now part of a more general "state" command.  The text and
  43.  * graph commands used for switching between modes is now handled by the
  44.  * escape function (very few drivers require it).  The device-specific PLDev
  45.  * structure is now malloc'ed for each driver that requires it, and freed when
  46.  * the stream is terminated.
  47.  *
  48.  * Revision 1.10  1993/07/16  22:12:17  mjl
  49.  * Simplified and slightly changed behavior to support plot dumps to cloned
  50.  * plplot streams.
  51.  *
  52.  * Revision 1.9  1993/07/01  21:59:42  mjl
  53.  * Changed all plplot source files to include plplotP.h (private) rather than
  54.  * plplot.h.  Rationalized namespace -- all externally-visible plplot functions
  55.  * now start with "pl"; device driver functions start with "plD_".
  56. */
  57.  
  58. /*
  59.     plbuf.c -- handle plot buffer.
  60.  
  61.     Copyright 1992
  62.     Maurice LeBrun
  63.  
  64.     This software may be freely copied, modified and redistributed without
  65.     fee provided that this copyright notice is preserved intact on all
  66.     copies and modified copies.
  67.  
  68.     There is no warranty or other guarantee of fitness of this software.
  69.     It is provided solely "as is". The author(s) disclaim(s) all
  70.     responsibility and liability with respect to this software's usage or
  71.     its effect upon hardware or computer systems.
  72.  
  73. */
  74.  
  75. #include "plplotP.h"
  76. #include "drivers.h"
  77. #include "metadefs.h"
  78.  
  79. #include <string.h>
  80.  
  81. /* Function prototypes */
  82. /* INDENT OFF */
  83.  
  84. static int    rd_command    ( PLStream *pls, U_CHAR * );
  85. static int    wr_command    ( PLStream *pls, U_CHAR );
  86. static void    plbuf_control    ( PLStream *pls, U_CHAR );
  87.  
  88. void rdbuf_init        (PLStream *);
  89. void rdbuf_line        (PLStream *);
  90. void rdbuf_polyline    (PLStream *);
  91. void rdbuf_eop        (PLStream *);
  92. void rdbuf_bop        (PLStream *);
  93. void rdbuf_tidy        (PLStream *);
  94. void rdbuf_state    (PLStream *);
  95. void rdbuf_esc        (PLStream *);
  96.  
  97. static void plbuf_fill    (PLStream *pls);
  98. static void rdbuf_fill    (PLStream *pls);
  99.  
  100. /* INDENT ON */
  101. /*----------------------------------------------------------------------*\
  102. * Routines to write to the plot buffer.
  103. \*----------------------------------------------------------------------*/
  104.  
  105. /*----------------------------------------------------------------------*\
  106. * plbuf_init()
  107. *
  108. * Initialize device.
  109. * Actually just disables writes if plot buffer is already open (occurs
  110. * when one stream is cloned, as in printing).
  111. \*----------------------------------------------------------------------*/
  112.  
  113. void
  114. plbuf_init(PLStream *pls)
  115. {
  116.     dbug_enter("plbuf_init");
  117.  
  118.     if (pls->plbufFile != NULL) 
  119.     pls->plbuf_write = 0;
  120. }
  121.  
  122. /*----------------------------------------------------------------------*\
  123. * plbuf_line()
  124. *
  125. * Draw a line in the current color from (x1,y1) to (x2,y2).
  126. \*----------------------------------------------------------------------*/
  127.  
  128. void
  129. plbuf_line(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
  130. {
  131.     short xpl[2], ypl[2];
  132.  
  133.     dbug_enter("plbuf_line");
  134.  
  135.     wr_command(pls, (U_CHAR) LINE);
  136.  
  137.     xpl[0] = x1a;
  138.     xpl[1] = x2a;
  139.     ypl[0] = y1a;
  140.     ypl[1] = y2a;
  141.  
  142.     fwrite(xpl, sizeof(short), 2, pls->plbufFile);
  143.     fwrite(ypl, sizeof(short), 2, pls->plbufFile);
  144. }
  145.  
  146. /*----------------------------------------------------------------------*\
  147. * plbuf_polyline()
  148. *
  149. * Draw a polyline in the current color.
  150. \*----------------------------------------------------------------------*/
  151.  
  152. void
  153. plbuf_polyline(PLStream *pls, short *xa, short *ya, PLINT npts)
  154. {
  155.     dbug_enter("plbuf_polyline");
  156.  
  157.     wr_command(pls, (U_CHAR) POLYLINE);
  158.     fwrite(&npts, sizeof(PLINT), 1, pls->plbufFile);
  159.  
  160.     fwrite(xa, sizeof(short), npts, pls->plbufFile);
  161.     fwrite(ya, sizeof(short), npts, pls->plbufFile);
  162. }
  163.  
  164. /*----------------------------------------------------------------------*\
  165. * plbuf_eop()
  166. *
  167. * End of page.
  168. \*----------------------------------------------------------------------*/
  169.  
  170. void
  171. plbuf_eop(PLStream *pls)
  172. {
  173.     dbug_enter("plbuf_eop");
  174. }
  175.  
  176. /*----------------------------------------------------------------------*\
  177. * plbuf_bop()
  178. *
  179. * Set up for the next page.
  180. * To avoid problems redisplaying partially filled pages, on each BOP the
  181. * old file is thrown away and a new one is obtained.  This way we can just
  182. * read up to EOF to get everything on the current page.
  183. *
  184. * Also write state information to ensure the next page is correct.
  185. \*----------------------------------------------------------------------*/
  186.  
  187. void
  188. plbuf_bop(PLStream *pls)
  189. {
  190.     dbug_enter("plbuf_bop");
  191.  
  192.     plbuf_tidy(pls);
  193.  
  194.     pls->plbufFile = tmpfile();
  195.     if (pls->plbufFile == NULL) 
  196.     plexit("plbuf_init: Error opening plot data storage file.");
  197.  
  198.     plP_state(PLSTATE_COLOR0);
  199.     plP_state(PLSTATE_WIDTH);
  200. }
  201.  
  202. /*----------------------------------------------------------------------*\
  203. * plbuf_tidy()
  204. *
  205. * Close graphics file
  206. \*----------------------------------------------------------------------*/
  207.  
  208. void
  209. plbuf_tidy(PLStream *pls)
  210. {
  211.     dbug_enter("plbuf_tidy");
  212.  
  213.     if (pls->plbufFile == NULL)
  214.     return;
  215.  
  216.     fclose(pls->plbufFile);
  217.     pls->plbufFile = NULL;
  218. }
  219.  
  220. /*----------------------------------------------------------------------*\
  221. * plbuf_state()
  222. *
  223. * Handle change in PLStream state (color, pen width, fill attribute, etc).
  224. \*----------------------------------------------------------------------*/
  225.  
  226. void 
  227. plbuf_state(PLStream *pls, PLINT op)
  228. {
  229.     dbug_enter("plbuf_state");
  230.  
  231.     wr_command(pls, (U_CHAR) CHANGE_STATE);
  232.     wr_command(pls, (U_CHAR) op);
  233.  
  234.     switch (op) {
  235.  
  236.       case PLSTATE_WIDTH: {
  237.     U_CHAR width = pls->width;
  238.  
  239.     fwrite(&width, sizeof(U_CHAR), 1, pls->plbufFile);
  240.     break;
  241.       }
  242.  
  243.       case PLSTATE_COLOR0: {
  244.     U_CHAR icol0 = pls->icol0;
  245.     U_CHAR r = pls->curcolor.r;
  246.     U_CHAR g = pls->curcolor.g;
  247.     U_CHAR b = pls->curcolor.b;
  248.  
  249.     fwrite(&icol0, sizeof(U_CHAR), 1, pls->plbufFile);
  250.     if (icol0 == PL_RGB_COLOR) {
  251.         fwrite(&r, sizeof(U_CHAR), 1, pls->plbufFile);
  252.         fwrite(&g, sizeof(U_CHAR), 1, pls->plbufFile);
  253.         fwrite(&b, sizeof(U_CHAR), 1, pls->plbufFile);
  254.     }
  255.     break;
  256.       }
  257.  
  258.       case PLSTATE_COLOR1: {
  259.     U_CHAR icol1 = pls->icol1;
  260.  
  261.     fwrite(&icol1, sizeof(U_CHAR), 1, pls->plbufFile);
  262.     break;
  263.       }
  264.  
  265.       case PLSTATE_FILL:{
  266.     signed char patt = pls->patt;
  267.  
  268.     fwrite(&patt, sizeof(signed char), 1, pls->plbufFile);
  269.     break;
  270.       }
  271.     }
  272. }
  273.  
  274. /*----------------------------------------------------------------------*\
  275. * plbuf_esc()
  276. *
  277. * Escape function.  Note that any data written must be in device
  278. * independent form to maintain the transportability of the metafile.
  279. *
  280. * Functions:
  281. *
  282. *    PLESC_FILL    Fill polygon
  283. *
  284. \*----------------------------------------------------------------------*/
  285.  
  286. void
  287. plbuf_esc(PLStream *pls, PLINT op, void *ptr)
  288. {
  289.     dbug_enter("plbuf_esc");
  290.  
  291.     wr_command(pls, (U_CHAR) ESCAPE);
  292.     wr_command(pls, (U_CHAR) op);
  293.  
  294.     switch (op) {
  295.       case PLESC_FILL:
  296.     plbuf_fill(pls);
  297.     break;
  298.     }
  299. }
  300.  
  301. /*----------------------------------------------------------------------*\
  302. * plbuf_fill()
  303. *
  304. * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
  305. \*----------------------------------------------------------------------*/
  306.  
  307. static void
  308. plbuf_fill(PLStream *pls)
  309. {
  310.     dbug_enter("plbuf_fill");
  311.  
  312.     fwrite(&pls->dev_npts, sizeof(PLINT), 1, pls->plbufFile);
  313.     fwrite(pls->dev_x, sizeof(short), pls->dev_npts, pls->plbufFile);
  314.     fwrite(pls->dev_y, sizeof(short), pls->dev_npts, pls->plbufFile);
  315. }
  316.  
  317. /*----------------------------------------------------------------------*\
  318. * Routines to read from & process the plot buffer.
  319. \*----------------------------------------------------------------------*/
  320.  
  321. /*----------------------------------------------------------------------*\
  322. * rdbuf_init()
  323. *
  324. * Initialize device.
  325. \*----------------------------------------------------------------------*/
  326.  
  327. void
  328. rdbuf_init(PLStream *pls)
  329. {
  330.     dbug_enter("rdbuf_init");
  331. }
  332.  
  333. /*----------------------------------------------------------------------*\
  334. * rdbuf_line()
  335. *
  336. * Draw a line in the current color from (x1,y1) to (x2,y2).
  337. \*----------------------------------------------------------------------*/
  338.  
  339. void
  340. rdbuf_line(PLStream *pls)
  341. {
  342.     short xpl[2], ypl[2];
  343.     PLINT npts = 2;
  344.  
  345.     dbug_enter("rdbuf_line");
  346.  
  347.     fread(xpl, sizeof(short), npts, pls->plbufFile);
  348.     fread(ypl, sizeof(short), npts, pls->plbufFile);
  349.  
  350.     plP_line(xpl, ypl);
  351. }
  352.  
  353. /*----------------------------------------------------------------------*\
  354. * rdbuf_polyline()
  355. *
  356. * Draw a polyline in the current color.
  357. \*----------------------------------------------------------------------*/
  358.  
  359. void
  360. rdbuf_polyline(PLStream *pls)
  361. {
  362.     short xpl[PL_MAXPOLY], ypl[PL_MAXPOLY];
  363.     PLINT npts;
  364.  
  365.     dbug_enter("rdbuf_polyline");
  366.  
  367.     fread(&npts, sizeof(PLINT), 1, pls->plbufFile);
  368.     fread(xpl, sizeof(short), npts, pls->plbufFile);
  369.     fread(ypl, sizeof(short), npts, pls->plbufFile);
  370.  
  371.     plP_polyline(xpl, ypl, npts);
  372. }
  373.  
  374. /*----------------------------------------------------------------------*\
  375. * rdbuf_eop()
  376. *
  377. * End of page.
  378. \*----------------------------------------------------------------------*/
  379.  
  380. void
  381. rdbuf_eop(PLStream *pls)
  382. {
  383.     dbug_enter("rdbuf_eop");
  384. }
  385.  
  386. /*----------------------------------------------------------------------*\
  387. * rdbuf_bop()
  388. *
  389. * Set up for the next page.
  390. \*----------------------------------------------------------------------*/
  391.  
  392. void
  393. rdbuf_bop(PLStream *pls)
  394. {
  395.     dbug_enter("rdbuf_bop");
  396. }
  397.  
  398. /*----------------------------------------------------------------------*\
  399. * rdbuf_tidy()
  400. *
  401. * Close graphics file
  402. \*----------------------------------------------------------------------*/
  403.  
  404. void
  405. rdbuf_tidy(PLStream *pls)
  406. {
  407.     dbug_enter("rdbuf_tidy");
  408. }
  409.  
  410. /*----------------------------------------------------------------------*\
  411. * rdbuf_state()
  412. *
  413. * Handle change in PLStream state (color, pen width, fill attribute, etc).
  414. \*----------------------------------------------------------------------*/
  415.  
  416. void 
  417. rdbuf_state(PLStream *pls)
  418. {
  419.     U_CHAR op;
  420.  
  421.     dbug_enter("rdbuf_state");
  422.  
  423.     fread(&op, sizeof(U_CHAR), 1, pls->plbufFile);
  424.  
  425.     switch (op) {
  426.  
  427.       case PLSTATE_WIDTH:{
  428.     U_CHAR width;
  429.  
  430.     fread(&width, sizeof(U_CHAR), 1, pls->plbufFile);
  431.     pls->width = width;
  432.     plP_state(PLSTATE_WIDTH);
  433.  
  434.     break;
  435.       }
  436.  
  437.       case PLSTATE_COLOR0:{
  438.     U_CHAR icol0, r, g, b;
  439.  
  440.     fread(&icol0, sizeof(U_CHAR), 1, pls->plbufFile);
  441.     if (icol0 == PL_RGB_COLOR) {
  442.         fread(&r, sizeof(U_CHAR), 1, pls->plbufFile);
  443.         fread(&g, sizeof(U_CHAR), 1, pls->plbufFile);
  444.         fread(&b, sizeof(U_CHAR), 1, pls->plbufFile);
  445.     }
  446.     else {
  447.         if ((int) icol0 > 15) {
  448.         plwarn("rdbuf_state: Color map 0 entry hosed");
  449.         icol0 = 1;
  450.         }
  451.         r = pls->cmap0[icol0].r;
  452.         g = pls->cmap0[icol0].g;
  453.         b = pls->cmap0[icol0].b;
  454.     }
  455.     pls->icol0 = icol0;
  456.     pls->curcolor.r = r;
  457.     pls->curcolor.g = g;
  458.     pls->curcolor.b = b;
  459.  
  460.     plP_state(PLSTATE_COLOR0);
  461.     break;
  462.       }
  463.  
  464.       case PLSTATE_COLOR1: {
  465.     U_CHAR icol1;
  466.  
  467.     fread(&icol1, sizeof(U_CHAR), 1, pls->plbufFile);
  468.  
  469.     pls->icol1 = icol1;
  470.     pls->curcolor.r = pls->cmap1[icol1].r;
  471.     pls->curcolor.g = pls->cmap1[icol1].g;
  472.     pls->curcolor.b = pls->cmap1[icol1].b;
  473.  
  474.     plP_state(PLSTATE_COLOR1);
  475.     break;
  476.       }
  477.  
  478.       case PLSTATE_FILL: {
  479.     signed char patt;
  480.  
  481.     fread(&patt, sizeof(signed char), 1, pls->plbufFile);
  482.  
  483.     pls->patt = patt;
  484.     plP_state(PLSTATE_FILL);
  485.     break;
  486.       }
  487.     }
  488. }
  489.  
  490. /*----------------------------------------------------------------------*\
  491. * rdbuf_esc()
  492. *
  493. * Escape function.
  494. * Must fill data structure with whatever data that was written,
  495. * then call escape function.
  496. *
  497. * Note: it is best to only call the escape function for op-codes that
  498. * are known to be supported.
  499. *
  500. * Functions:
  501. *
  502. *    PLESC_FILL    Fill polygon
  503. *
  504. \*----------------------------------------------------------------------*/
  505.  
  506. void
  507. rdbuf_esc(PLStream *pls)
  508. {
  509.     U_CHAR op;
  510.  
  511.     dbug_enter("rdbuf_esc");
  512.  
  513.     fread(&op, sizeof(U_CHAR), 1, pls->plbufFile);
  514.  
  515.     switch (op) {
  516.       case PLESC_FILL:
  517.     rdbuf_fill(pls);
  518.     break;
  519.     }
  520. }
  521.  
  522. /*----------------------------------------------------------------------*\
  523. * rdbuf_fill()
  524. *
  525. * Fill polygon described by input points.
  526. \*----------------------------------------------------------------------*/
  527.  
  528. static void
  529. rdbuf_fill(PLStream *pls)
  530. {
  531.     short xpl[PL_MAXPOLY], ypl[PL_MAXPOLY];
  532.     PLINT npts;
  533.  
  534.     dbug_enter("rdbuf_fill");
  535.  
  536.     fread(&npts, sizeof(PLINT), 1, pls->plbufFile);
  537.     fread(xpl, sizeof(short), npts, pls->plbufFile);
  538.     fread(ypl, sizeof(short), npts, pls->plbufFile);
  539.  
  540.     plP_fill(xpl, ypl, npts);
  541. }
  542.  
  543. /*----------------------------------------------------------------------*\
  544. * plRemakePlot()
  545. *
  546. * Rebuilds plot from plot buffer, usually in response to a window
  547. * resize or exposure event.
  548. \*----------------------------------------------------------------------*/
  549.  
  550. void
  551. plRemakePlot(PLStream *pls)
  552. {
  553.     U_CHAR c;
  554.     int plbuf_status;
  555.  
  556.     dbug_enter("plRemakePlot");
  557.  
  558.     if (pls->plbufFile == NULL)
  559.     return;
  560.  
  561.     rewind(pls->plbufFile);
  562.  
  563.     plbuf_status = pls->plbuf_write;
  564.     pls->plbuf_write = FALSE;
  565.     while (rd_command(pls, &c)) {
  566.     plbuf_control(pls, c);
  567.     }
  568.  
  569.     pls->plbuf_write = plbuf_status;
  570. }
  571.  
  572. /*----------------------------------------------------------------------*\
  573. * plbuf_control()
  574. *
  575. * Processes commands read from the plot buffer.
  576. \*----------------------------------------------------------------------*/
  577.  
  578. static void
  579. plbuf_control(PLStream *pls, U_CHAR c)
  580. {
  581.     static U_CHAR c_old = 0;
  582.  
  583.     dbug_enter("plbuf_control");
  584.  
  585.     switch ((int) c) {
  586.  
  587.       case INITIALIZE:
  588.     rdbuf_init(pls);
  589.     break;
  590.  
  591.       case EOP:
  592.     rdbuf_eop(pls);
  593.     break;
  594.  
  595.       case BOP:
  596.     rdbuf_bop(pls);
  597.     break;
  598.  
  599.       case CHANGE_STATE:
  600.     rdbuf_state(pls);
  601.     break;
  602.  
  603.       case LINE:
  604.     rdbuf_line(pls);
  605.     break;
  606.  
  607.       case POLYLINE:
  608.     rdbuf_polyline(pls);
  609.     break;
  610.  
  611.       case ESCAPE:
  612.     rdbuf_esc(pls);
  613.     break;
  614.  
  615.       default:
  616.     fprintf(stderr,
  617.         "plbuf_control: Unrecognized command %d, previous %d\n",
  618.         c, c_old);
  619.     }
  620.     c_old = c;
  621. }
  622.  
  623. /*----------------------------------------------------------------------*\
  624. *  rd_command()
  625. *
  626. *  Read & return the next command
  627. \*----------------------------------------------------------------------*/
  628.  
  629. static int
  630. rd_command(PLStream *pls, U_CHAR *p_c)
  631. {
  632.     int count;
  633.     
  634.     count = fread(p_c, sizeof(U_CHAR), 1, pls->plbufFile);
  635.     return (count);
  636. }
  637.  
  638. /*----------------------------------------------------------------------*\
  639. *  wr_command()
  640. *
  641. *  Write the next command
  642. \*----------------------------------------------------------------------*/
  643.  
  644. static int
  645. wr_command(PLStream *pls, U_CHAR c)
  646. {
  647.     U_CHAR c1 = c;
  648.     int count;
  649.  
  650.     count = fwrite(&c1, sizeof(U_CHAR), 1, pls->plbufFile);
  651.     return (count);
  652. }
  653.