racket/src/plot/plplot/dc_drv.c
Matthew Flatt 514706446e overhaul plot organization
by moving needed C source to src/plot and building during `make',
 but stripping out the copies of gd, png, and zlib; instead, hook
 a dc<%>-based back end into plot
2010-11-06 16:54:29 -06:00

267 lines
6.8 KiB
C

/*
Device driver whose handlers are inplemented in Racket
using dc<%>.
*/
#include "plDevs.h"
#include "plplotP.h"
#include "drivers.h"
/* Device info */
char* plD_DEVICE_INFO_dc = "dc:dc<%>:0:dc:50:dc";
void plD_init_dc (PLStream *);
void plD_line_dc (PLStream *, short, short, short, short);
void plD_polyline_dc (PLStream *, short *, short *, PLINT);
void plD_eop_dc (PLStream *);
void plD_eop_jpeg (PLStream *);
void plD_bop_dc (PLStream *);
void plD_tidy_dc (PLStream *);
void plD_state_dc (PLStream *, PLINT);
void plD_esc_dc (PLStream *, PLINT, void *);
typedef struct {
void *p;
void (*drawLine)(void *p, short x1a, short y1a, short x2a, short y2a);
void (*drawLines)(void *p, short *xa, short *ya, PLINT npts);
void (*fillPoly)(void *p, short *xa, short *ya, PLINT npts);
void (*setWidth)(void *p, int w);
void (*setColor)(void *p, short i);
void (*setColorRGB)(void *p, short r, short g, short b);
void (*startPage)(void *p);
void (*endPage)(void *p);
void (*endDoc)(void *p);
} dc_Dev;
void plD_dispatch_init_dc( PLDispatchTable *pdt )
{
pdt->pl_MenuStr = "drawing context";
pdt->pl_DevName = "dc<%>";
pdt->pl_type = plDevType_FileOriented;
pdt->pl_seq = 50;
pdt->pl_init = (plD_init_fp) plD_init_dc;
pdt->pl_line = (plD_line_fp) plD_line_dc;
pdt->pl_polyline = (plD_polyline_fp) plD_polyline_dc;
pdt->pl_eop = (plD_eop_fp) plD_eop_dc;
pdt->pl_bop = (plD_bop_fp) plD_bop_dc;
pdt->pl_tidy = (plD_tidy_fp) plD_tidy_dc;
pdt->pl_state = (plD_state_fp) plD_state_dc;
pdt->pl_esc = (plD_esc_fp) plD_esc_dc;
}
/*--------------------------------------------------------------------------*\
* plD_init_dc_Dev()
*
\*--------------------------------------------------------------------------*/
static void
plD_init_dc_Dev(PLStream *pls)
{
/* Allocate and initialize device-specific data */
dc_Dev *dev;
if (pls->dev != NULL)
free((void *) pls->dev);
pls->dev = calloc(1, (size_t) sizeof(dc_Dev));
if (pls->dev == NULL)
plexit("plD_init_dc_Dev: Out of memory.");
dev = (dc_Dev *) pls->dev;
}
/*----------------------------------------------------------------------*\
* plD_init_dc()
*
* Initialize device.
\*----------------------------------------------------------------------*/
void plD_init_dc(PLStream *pls)
{
dc_Dev *dev;
pls->termin = 0; /* Not an interactive device */
pls->icol0 = 1;
pls->bytecnt = 0;
pls->page = 0;
pls->dev_fill0 = 1; /* Can do solid fills */
if (!pls->colorset)
pls->color = 1; /* Is a color device */
/* Initialize family file info */
plFamInit(pls);
/* Allocate and initialize device-specific data */
plD_init_dc_Dev(pls);
dev=(dc_Dev *)pls->dev;
if (pls->xlength <= 0 || pls->ylength <=0)
{
/* use default width, height of 800x600 if not specifed by -geometry option
* or plspage */
plspage(0., 0., 800, 600, 0, 0);
}
pls->graphx = GRAPHICS_MODE;
if (pls->xdpi<=0)
{
/* This corresponds to a typical monitor resolution of 4 pixels/mm. */
plspage(4.*25.4, 4.*25.4, 0, 0, 0, 0);
}
else
{
pls->ydpi=pls->xdpi; /* Set X and Y dpi's to the same value */
}
/* Convert DPI to pixels/mm */
plP_setpxl(1*pls->xdpi/25.4,1*pls->ydpi/25.4);
plP_setphy(0, 1*(pls->xlength - 1), 0, 1*(pls->ylength - 1));
}
/*----------------------------------------------------------------------*\
* plD_line_dc()
*
* Draw a line in the current color from (x1,y1) to (x2,y2).
\*----------------------------------------------------------------------*/
void
plD_line_dc(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
{
dc_Dev *dev=(dc_Dev *)pls->dev;
if (dev->drawLine)
dev->drawLine(dev->p, x1a, y1a, x2a, y2a);
}
/*----------------------------------------------------------------------*\
* plD_polyline_dc()
*
* Draw a polyline in the current color.
\*----------------------------------------------------------------------*/
void
plD_polyline_dc(PLStream *pls, short *xa, short *ya, PLINT npts)
{
dc_Dev *dev=(dc_Dev *)pls->dev;
if (dev->drawLines)
dev->drawLines(dev->p, xa, ya, npts);
}
/*----------------------------------------------------------------------*\
* fill_polygon()
*
* Fill polygon described in points pls->dev_x[] and pls->dev_y[].
\*----------------------------------------------------------------------*/
static void
fill_polygon(PLStream *pls)
{
dc_Dev *dev=(dc_Dev *)pls->dev;
if (dev->fillPoly)
dev->fillPoly(dev->p, pls->dev_x, pls->dev_y, pls->dev_npts);
}
/*----------------------------------------------------------------------*\
* plD_state_dc()
*
* Handle change in PLStream state (color, pen width, fill attribute, etc).
\*----------------------------------------------------------------------*/
void
plD_state_dc(PLStream *pls, PLINT op)
{
dc_Dev *dev=(dc_Dev *)pls->dev;
switch (op) {
case PLSTATE_WIDTH:
if (dev->setWidth)
dev->setWidth(dev->p, pls->width);
break;
case PLSTATE_COLOR0:
if (pls->icol0 == PL_RGB_COLOR) {
if (dev->setColorRGB)
dev->setColorRGB(dev->p, pls->curcolor.r, pls->curcolor.g, pls->curcolor.b);
} else {
if (dev->setColor)
dev->setColor(dev->p, pls->icol0);
}
break;
case PLSTATE_COLOR1:
if (dev->setColorRGB)
dev->setColorRGB(dev->p, pls->curcolor.r, pls->curcolor.g, pls->curcolor.b);
break;
}
}
/*----------------------------------------------------------------------*\
* plD_esc_dc()
*
* Escape function.
\*----------------------------------------------------------------------*/
void plD_esc_dc(PLStream *pls, PLINT op, void *ptr)
{
switch (op) {
case PLESC_FILL: /* fill */
fill_polygon(pls);
break;
}
}
/*----------------------------------------------------------------------*\
* plD_bop_dc()
*
* Set up for the next page.
* Advance to next family file if necessary (file output).
\*----------------------------------------------------------------------*/
void plD_bop_dc(PLStream *pls)
{
dc_Dev *dev=(dc_Dev *)pls->dev;
if (dev->startPage)
dev->startPage(dev->p);
}
/*----------------------------------------------------------------------*\
* plD_tidy_dc()
*
* Close graphics file or otherwise clean up.
\*----------------------------------------------------------------------*/
void plD_tidy_dc(PLStream *pls)
{
dc_Dev *dev=(dc_Dev *)pls->dev;
if (dev->endDoc)
dev->endDoc(dev->p);
}
/*----------------------------------------------------------------------*\
* plD_eop_dc()
*
* End of page.
\*----------------------------------------------------------------------*/
void plD_eop_dc(PLStream *pls)
{
dc_Dev *dev=(dc_Dev *)pls->dev;
if (dev->endPage)
dev->endPage(dev->p);
}