1 // PLplot MEM (in user-supplied memory) device driver.
2 // The idea here is that the user will specify the Y by X by RGB
3 // area in which to plot using the plsmem function (added by me).
4 //
5 // This is a bare-bones driver which allows one to plot on an existing
6 // image in memory.  This is useful if the user has an image in memory
7 // that he wants to decorate with PLPLOT.
8 //
9 // Contributed by Doug Hunt
10 // Included in PLplot by Rafael Laboissiere on Sat Feb 22 18:34:06 CET 2003
11 //
12 
13 #include "plDevs.h"
14 
15 #ifdef PLD_mem
16 
17 #include "plplotP.h"
18 #include "drivers.h"
19 
20 // Device info
21 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_mem = "mem:User-supplied memory device:-1:mem:46:mem\n";
22 
23 void plD_dispatch_init_mem( PLDispatchTable *pdt );
24 
25 void plD_init_mem( PLStream * );
26 void plD_line_mem( PLStream *, short, short, short, short );
27 void plD_polyline_mem( PLStream *, short *, short *, PLINT );
28 void plD_eop_mem( PLStream * );
29 void plD_bop_mem( PLStream * );
30 void plD_tidy_mem( PLStream * );
31 void plD_state_mem( PLStream *, PLINT );
32 void plD_esc_mem( PLStream *, PLINT, void * );
33 
34 #undef MAX
35 #undef ABS
36 #define MAX( a, b )    ( ( a > b ) ? a : b )
37 #define ABS( a )       ( ( a < 0 ) ? -a : a )
38 
39 #define MAX_INTENSITY    255
40 
plD_dispatch_init_mem(PLDispatchTable * pdt)41 void plD_dispatch_init_mem( PLDispatchTable *pdt )
42 {
43 #ifndef ENABLE_DYNDRIVERS
44     pdt->pl_MenuStr = "User-supplied memory device";
45     pdt->pl_DevName = "mem";
46 #endif
47     pdt->pl_type     = plDevType_Null;
48     pdt->pl_seq      = 45;
49     pdt->pl_init     = (plD_init_fp) plD_init_mem;
50     pdt->pl_line     = (plD_line_fp) plD_line_mem;
51     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_mem;
52     pdt->pl_eop      = (plD_eop_fp) plD_eop_mem;
53     pdt->pl_bop      = (plD_bop_fp) plD_bop_mem;
54     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_mem;
55     pdt->pl_state    = (plD_state_fp) plD_state_mem;
56     pdt->pl_esc      = (plD_esc_fp) plD_esc_mem;
57 }
58 
59 //--------------------------------------------------------------------------
60 // plD_init_mem()
61 //
62 // Initialize device (terminal).
63 //--------------------------------------------------------------------------
64 
65 void
plD_init_mem(PLStream * pls)66 plD_init_mem( PLStream *pls )
67 {
68     // plsmem must have already been called to set pls->dev to the
69     // user supplied plotting area.  The dimensions of the plot area
70     // have also been set by plsmem.  Verify this.
71     //
72 
73     if ( ( pls->phyxma == 0 ) || ( pls->dev == NULL ) )
74     {
75         plexit( "Must call plsmem first to set user plotting area!" );
76     }
77 
78     if ( pls->dev_mem_alpha == 1 )
79     {
80         plexit( "The mem driver does not support alpha values! Use plsmem!" );
81     }
82 
83     plP_setpxl( (PLFLT) 4, (PLFLT) 4 ); // rough pixels/mm on *my* screen
84 
85 
86     pls->color     = 1;         // Is a color device
87     pls->dev_fill0 = 0;         // Handle solid fills
88     pls->dev_fill1 = 0;         // Use PLplot core fallback for pattern fills
89     pls->nopause   = 1;         // Don't pause between frames
90 }
91 
92 #define sign( a )    ( ( a < 0 ) ? -1 : ( ( a == 0 ) ? 0 : 1 ) )
93 
94 void
plD_line_mem(PLStream * pls,short x1a,short y1a,short x2a,short y2a)95 plD_line_mem( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
96 {
97     int           i;
98     PLINT         idx;
99     int           x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
100     PLINT         x1b, y1b, x2b, y2b;
101     PLFLT         length, fx, fy, dx, dy;
102     unsigned char *mem = (unsigned char *) pls->dev;
103     PLINT         xm   = pls->phyxma;
104     PLINT         ym   = pls->phyyma;
105 
106     // Take mirror image, since (0,0) must be at top left
107 
108     y1 = ym - ( y1 - 0 );
109     y2 = ym - ( y2 - 0 );
110 
111     x1b    = x1, x2b = x2, y1b = y1, y2b = y2;
112     length = (PLFLT) sqrt( (double)
113         ( ( x2b - x1b ) * ( x2b - x1b ) + ( y2b - y1b ) * ( y2b - y1b ) ) );
114 
115     if ( length == 0. )
116         length = 1.;
117     dx = ( x2 - x1 ) / length;
118     dy = ( y2 - y1 ) / length;
119 
120     fx = x1;
121     fy = y1;
122     mem[3 * xm * y1 + 3 * x1 + 0] = pls->curcolor.r;
123     mem[3 * xm * y1 + 3 * x1 + 1] = pls->curcolor.g;
124     mem[3 * xm * y1 + 3 * x1 + 2] = pls->curcolor.b;
125 
126     mem[3 * xm * y2 + 3 * x2 + 0] = pls->curcolor.r;
127     mem[3 * xm * y2 + 3 * x2 + 1] = pls->curcolor.g;
128     mem[3 * xm * y2 + 3 * x2 + 2] = pls->curcolor.b;
129 
130     for ( i = 1; i <= (int) length; i++ )
131     {
132         fx          += dx;
133         fy          += dy;
134         idx          = 3 * xm * (PLINT) fy + 3 * (PLINT) fx;
135         mem[idx + 0] = pls->curcolor.r;
136         mem[idx + 1] = pls->curcolor.g;
137         mem[idx + 2] = pls->curcolor.b;
138     }
139 }
140 
141 void
plD_polyline_mem(PLStream * pls,short * xa,short * ya,PLINT npts)142 plD_polyline_mem( PLStream *pls, short *xa, short *ya, PLINT npts )
143 {
144     int i;
145     for ( i = 0; i < npts - 1; i++ )
146         plD_line_mem( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
147 }
148 
149 void
plD_eop_mem(PLStream * pls)150 plD_eop_mem( PLStream *pls )
151 {
152     // Set the 'dev' member (which holds the user supplied memory image)
153     // to NULL here so it won't be freed when PLplot is closed.
154     // (the user is responsible for freeing it when ready).
155     //
156     pls->dev = NULL;
157 }
158 
159 void
plD_bop_mem(PLStream * PL_UNUSED (pls))160 plD_bop_mem( PLStream * PL_UNUSED( pls ) )
161 {
162 // Nothing to do here
163 }
164 
165 void
plD_tidy_mem(PLStream * PL_UNUSED (pls))166 plD_tidy_mem( PLStream * PL_UNUSED( pls ) )
167 {
168 // Nothing to do here
169 }
170 
171 void
plD_state_mem(PLStream * PL_UNUSED (pls),PLINT PL_UNUSED (op))172 plD_state_mem( PLStream * PL_UNUSED( pls ), PLINT PL_UNUSED( op ) )
173 {
174 // Nothing to do here
175 }
176 
177 void
plD_esc_mem(PLStream * PL_UNUSED (pls),PLINT PL_UNUSED (op),void * PL_UNUSED (ptr))178 plD_esc_mem( PLStream *PL_UNUSED( pls ), PLINT PL_UNUSED( op ), void * PL_UNUSED( ptr ) )
179 {
180 // Nothing to do here
181 }
182 
183 #endif                          // PLD_mem
184