PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
ljiip.c
Go to the documentation of this file.
1 // PLplot Laser Jet IIp device driver.
2 // Based on old LJII driver, modifications by Wesley Ebisuzaki
3 //
4 // DPI = 300, 150, 100 (dots per inch)
5 // default: Unix 300 dpi, MS-DOS 150 dpi
6 // higher = better output, more memory, longer to print
7 // GCMODE = 0, 2 (graphics compression mode)
8 // default: 2, old laser jets should use 0
9 // compression can speed up the printing up to 3x
10 //
11 //
12 #include "plDevs.h"
13 
14 #ifdef PLD_ljiip
15 
16 #include "plplotP.h"
17 #include "drivers.h"
18 #include <math.h>
19 #include <string.h>
20 
21 #ifdef __GO32__ // dos386/djgpp
22 #ifdef MSDOS
23 #undef MSDOS
24 #endif
25 #endif
26 
27 // Device info
28 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_ljiip =
29  "ljiip:LaserJet IIp/deskjet compressed graphics:0:ljiip:32:ljiip\n";
30 
31 // Function prototypes
32 
34 
35 void plD_init_ljiip( PLStream * );
36 void plD_line_ljiip( PLStream *, short, short, short, short );
37 void plD_polyline_ljiip( PLStream *, short *, short *, PLINT );
38 void plD_eop_ljiip( PLStream * );
39 void plD_bop_ljiip( PLStream * );
40 void plD_tidy_ljiip( PLStream * );
41 void plD_state_ljiip( PLStream *, PLINT );
42 void plD_esc_ljiip( PLStream *, PLINT, void * );
43 
44 static void setpoint( PLINT, PLINT );
45 
46 // top level declarations
47 
48 // GCMODE = graphics compression mode, 0=old laser jets, 2=ljiip or later
49 #define GCMODE 2
50 
51 // DPI = dots per inch, more dots=better plot, more memory, more time
52 // possible DPI = 75, 100, 150, 300
53 // if DPI=300 then your machine must have a free 1Mb block of memory
54 
55 #define DPI 300
56 
57 #ifdef MSDOS
58 #undef DPI
59 #define DPI 150
60 #endif
61 
62 #define OF pls->OutFile
63 #define CURX ( (long) ( DPI / 5 ) )
64 #define CURY ( (long) ( DPI / 7 ) )
65 #define XDOTS ( 376 * ( DPI / 50 ) ) // # dots across
66 #define YDOTS ( 500 * ( DPI / 50 ) ) // # dots down
67 #define JETX ( XDOTS - 1 )
68 #define JETY ( YDOTS - 1 )
69 
70 
71 #define BPROW ( XDOTS / 8L ) // # bytes across
72 #define MAX_WID 8 // max pen width in pixels
73 #define BPROW1 ( BPROW + ( MAX_WID + 7 ) / 8 ) // pen has width, make bitmap bigger
74 #define NBYTES BPROW1 * ( YDOTS + MAX_WID ) // total number of bytes
75 
76 // Graphics control characters.
77 
78 #define ESC 0x1b
79 #define FF 0x0c
80 
81 static char mask[8] =
82 { '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001' };
83 
84 #ifndef MSDOS
85 #define _HUGE
86 #else
87 #define _HUGE _huge
88 #endif
89 
90 static unsigned char _HUGE *bitmap; // memory area NBYTES in size
91 
93 {
94 #ifndef ENABLE_DYNDRIVERS
95  pdt->pl_MenuStr = "LaserJet IIp/deskjet compressed graphics";
96  pdt->pl_DevName = "ljiip";
97 #endif
99  pdt->pl_seq = 32;
100  pdt->pl_init = (plD_init_fp) plD_init_ljiip;
101  pdt->pl_line = (plD_line_fp) plD_line_ljiip;
102  pdt->pl_polyline = (plD_polyline_fp) plD_polyline_ljiip;
103  pdt->pl_eop = (plD_eop_fp) plD_eop_ljiip;
104  pdt->pl_bop = (plD_bop_fp) plD_bop_ljiip;
105  pdt->pl_tidy = (plD_tidy_fp) plD_tidy_ljiip;
106  pdt->pl_state = (plD_state_fp) plD_state_ljiip;
107  pdt->pl_esc = (plD_esc_fp) plD_esc_ljiip;
108 }
109 
110 //--------------------------------------------------------------------------
111 // plD_init_ljiip()
112 //
113 // Initialize device.
114 //--------------------------------------------------------------------------
115 
116 void
117 plD_init_ljiip( PLStream *pls )
118 {
119  PLDev *dev;
120 
121  if ( pls->width == 0 ) // Is 0 if uninitialized
122  pls->width = DPI / 100;
123 
124 // Initialize family file info
125 
126  plFamInit( pls );
127 
128 // Prompt for a file name if not already set
129 
130  plOpenFile( pls );
131 
132 // Allocate and initialize device-specific data
133 
134  dev = plAllocDev( pls );
135 
136  dev->xold = PL_UNDEFINED;
137  dev->yold = PL_UNDEFINED;
138  dev->xmin = 0;
139  dev->ymin = 0;
140 
141 // number of pixels / mm
142 
143  plP_setpxl( (PLFLT) ( DPI / 25.4 ), (PLFLT) ( DPI / 25.4 ) );
144 
145 // Rotate by 90 degrees since portrait mode addressing is used
146 
147  dev->xmin = 0;
148  dev->ymin = 0;
149  dev->xmax = JETY;
150  dev->ymax = JETX;
151  dev->xlen = dev->xmax - dev->xmin;
152  dev->ylen = dev->ymax - dev->ymin;
153 
154  plP_setphy( dev->xmin, dev->xmax, dev->ymin, dev->ymax );
155 
156 // If portrait mode is specified, then set up an additional rotation
157 // transformation with aspect ratio allowed to adjust via freeaspect.
158 // Default orientation is landscape (ORIENTATION == 3 or 90 deg rotation
159 // counter-clockwise from portrait). (Legacy PLplot used seascape
160 // which was equivalent to ORIENTATION == 1 or 90 deg clockwise rotation
161 // from portrait.)
162 
163  if ( pls->portrait )
164  {
165  plsdiori( (PLFLT) ( 4 - ORIENTATION ) );
166  pls->freeaspect = 1;
167  }
168 
169 // Allocate storage for bit map matrix
170 
171 #ifdef MSDOS
172  if ( ( bitmap = (unsigned char _HUGE *)
173  halloc( (long) NBYTES, sizeof ( char ) ) ) == NULL )
174  plexit( "Out of memory in call to calloc" );
175 #else
176  if ( ( bitmap = (unsigned char *) calloc( NBYTES, sizeof ( char ) ) ) == NULL )
177  plexit( "Out of memory in call to calloc" );
178 #endif
179 
180 // Reset Printer
181 
182  fprintf( OF, "%cE", ESC );
183 }
184 
185 //--------------------------------------------------------------------------
186 // plD_line_ljiip()
187 //
188 // Draw a line in the current color from (x1,y1) to (x2,y2).
189 //--------------------------------------------------------------------------
190 
191 void
192 plD_line_ljiip( PLStream *pls, short x1a, short y1a, short x2a, short y2a )
193 {
194  PLDev *dev = (PLDev *) pls->dev;
195  int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
196  int abs_dx, abs_dy, dx, dy, incx, incy;
197  int i, j, width, residual;
198  PLFLT tmp;
199 
200  width = MIN( pls->width, MAX_WID );
201 
202 // Take mirror image, since PCL expects (0,0) to be at top left
203 
204  y1 = dev->ymax - ( y1 - dev->ymin );
205  y2 = dev->ymax - ( y2 - dev->ymin );
206 
207 // Rotate by 90 degrees
208 
209  plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x1, &y1 );
210  plRotPhy( ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &x2, &y2 );
211 
212  dx = x2 - x1;
213  dy = y2 - y1;
214 
215  if ( dx < 0 )
216  {
217  abs_dx = -dx;
218  incx = -1;
219  }
220  else
221  {
222  abs_dx = dx;
223  incx = 1;
224  }
225  if ( dy < 0 )
226  {
227  abs_dy = -dy;
228  incy = -1;
229  }
230  else
231  {
232  abs_dy = dy;
233  incy = 1;
234  }
235 
236 // make pixel width narrower for diag lines
237 
238  if ( abs_dy <= abs_dx )
239  {
240  if ( abs_dx == 0 )
241  tmp = 1.0;
242  else
243  tmp = 1.0 - (PLFLT) abs_dy / abs_dx;
244  }
245  else
246  {
247  tmp = 1.0 - (PLFLT) abs_dx / abs_dy;
248  }
249 
250  width = floor( 0.5 + width * ( tmp * tmp * tmp * ( 1.0 - 0.707107 ) + 0.707107 ) );
251 
252  if ( width < 1 )
253  width = 1;
254  if ( width > 1 )
255  {
256  for ( i = 0; i < width; i++ )
257  {
258  for ( j = 0; j < width; j++ )
259  {
260  setpoint( (PLINT) ( x1 + i ), (PLINT) ( y1 + j ) );
261  setpoint( (PLINT) ( x2 + i ), (PLINT) ( y2 + j ) );
262  }
263  }
264  }
265  if ( abs_dx >= abs_dy )
266  {
267  residual = -( abs_dx >> 1 );
268  if ( width == 1 )
269  {
270  for ( i = 0; i <= abs_dx; i++, x1 += incx )
271  {
272  setpoint( (PLINT) ( x1 ), (PLINT) ( y1 ) );
273  if ( ( residual += abs_dy ) >= 0 )
274  {
275  residual -= abs_dx;
276  y1 += incy;
277  }
278  }
279  }
280  else
281  {
282  for ( i = 0; i <= abs_dx; i++, x1 += incx )
283  {
284  for ( j = 0; j < width; j++ )
285  {
286  setpoint( (PLINT) ( x1 ), (PLINT) ( y1 + j ) );
287  setpoint( (PLINT) ( x1 + width - 1 ), (PLINT) ( y1 + j ) );
288  }
289  if ( ( residual += abs_dy ) >= 0 )
290  {
291  residual -= abs_dx;
292  y1 += incy;
293  }
294  }
295  }
296  }
297  else
298  {
299  residual = -( abs_dy >> 1 );
300  if ( width == 1 )
301  {
302  for ( i = 0; i <= abs_dy; i++, y1 += incy )
303  {
304  setpoint( (PLINT) ( x1 ), (PLINT) ( y1 ) );
305  if ( ( residual += abs_dx ) >= 0 )
306  {
307  residual -= abs_dy;
308  x1 += incx;
309  }
310  }
311  }
312  else
313  {
314  for ( i = 0; i <= abs_dy; i++, y1 += incy )
315  {
316  for ( j = 0; j < width; j++ )
317  {
318  setpoint( (PLINT) ( x1 + j ), (PLINT) ( y1 ) );
319  setpoint( (PLINT) ( x1 + j ), (PLINT) ( y1 + width - 1 ) );
320  }
321  if ( ( residual += abs_dx ) >= 0 )
322  {
323  residual -= abs_dy;
324  x1 += incx;
325  }
326  }
327  }
328  }
329 }
330 
331 //--------------------------------------------------------------------------
332 // plD_polyline_ljiip()
333 //
334 // Draw a polyline in the current color.
335 //--------------------------------------------------------------------------
336 
337 void
338 plD_polyline_ljiip( PLStream *pls, short *xa, short *ya, PLINT npts )
339 {
340  PLINT i;
341 
342  for ( i = 0; i < npts - 1; i++ )
343  plD_line_ljiip( pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
344 }
345 
346 //--------------------------------------------------------------------------
347 // plD_eop_ljiip()
348 //
349 // End of page.(prints it here).
350 //--------------------------------------------------------------------------
351 
352 void
353 plD_eop_ljiip( PLStream *pls )
354 {
355  PLINT j;
356  unsigned char _HUGE *p;
357 #if GCMODE > 0
358  int i, iy, last, n, jmax;
359  unsigned char _HUGE t_buf[BPROW * 2];
360  unsigned char c;
361 #endif
362 
363 // PCL III setup: ref. Deskjet Plus Printer Owner's Manual
364 
365  fprintf( OF, "\033*rB" ); // end raster graphics
366  fprintf( OF, "\033*t%3dR", DPI ); // set DPI
367 
368 #if GCMODE != 0
369  fprintf( OF, "\033*r%dS", XDOTS ); // raster width
370  fprintf( OF, "\033*b%1dM", GCMODE ); // graphics mode
371 #endif
372 
373 // First move cursor to origin
374 
375  fprintf( OF, "\033*p%ldX", CURX );
376  fprintf( OF, "\033*p%ldY", CURY );
377  fprintf( OF, "\033*r0A" ); // start graphics
378 
379 // Write out raster data
380 
381 #if GCMODE == 0
382  for ( j = 0, p = bitmap; j < YDOTS; j++, p += BPROW1 )
383  {
384  fprintf( OF, "\033*b>%dW", BPROW );
385  fwrite( p, BPROW, sizeof ( char ), OF );
386  }
387 #endif
388 #if GCMODE == 2
389  for ( iy = 0, p = bitmap; iy < YDOTS; iy++, p += BPROW1 )
390  {
391  // find last non-zero byte
392 
393  last = BPROW - 1;
394  while ( last > 0 && p[last] == 0 )
395  last--;
396  last++;
397 
398  // translate to mode 2, save results in t_buf[]
399 
400  i = n = 0;
401  while ( i < last )
402  {
403  c = p[i];
404  jmax = i + 127;
405  jmax = last < jmax ? last : jmax;
406  if ( i < last - 2 && ( c == p[i + 1] ) && ( c == p[i + 2] ) )
407  {
408  j = i + 3;
409  while ( j < jmax && c == p[j] )
410  j++;
411  t_buf[n++] = ( i - j + 1 ) & 0xff;
412  t_buf[n++] = c;
413  i = j;
414  }
415  else
416  {
417  for ( j = i + 1; j < jmax; j++ )
418  {
419  if ( j < last - 2 && ( p[j] == p[j + 1] ) &&
420  ( p[j + 1] == p[j + 2] ) )
421  break;
422  }
423  t_buf[n++] = j - i - 1;
424  while ( i < j )
425  {
426  t_buf[n++] = p[i++];
427  }
428  }
429  }
430  fprintf( OF, "\033*b%dW", (int) n );
431  fwrite( t_buf, (int) n, sizeof ( char ), OF );
432  }
433 #endif
434 
435  pls->bytecnt += NBYTES;
436 
437 // End raster graphics and send Form Feed
438 
439  fprintf( OF, "\033*rB" );
440  fprintf( OF, "%c", FF );
441 
442 // Finally, clear out bitmap storage area
443 
444  memset( (void *) bitmap, '\0', NBYTES );
445 }
446 
447 //--------------------------------------------------------------------------
448 // plD_bop_ljiip()
449 //
450 // Set up for the next page.
451 // Advance to next family file if necessary (file output).
452 //--------------------------------------------------------------------------
453 
454 void
455 plD_bop_ljiip( PLStream *pls )
456 {
457  if ( !pls->termin )
458  plGetFam( pls );
459 
460  pls->page++;
461 }
462 
463 //--------------------------------------------------------------------------
464 // plD_tidy_ljiip()
465 //
466 // Close graphics file or otherwise clean up.
467 //--------------------------------------------------------------------------
468 
469 void
470 plD_tidy_ljiip( PLStream *pls )
471 {
472 // Reset Printer
473 
474  fprintf( OF, "%cE", ESC );
475  plCloseFile( pls );
476  free( (char *) bitmap );
477 }
478 
479 //--------------------------------------------------------------------------
480 // plD_state_ljiip()
481 //
482 // Handle change in PLStream state (color, pen width, fill attribute, etc).
483 //--------------------------------------------------------------------------
484 
485 void
486 plD_state_ljiip( PLStream *pls, PLINT op )
487 {
488 }
489 
490 //--------------------------------------------------------------------------
491 // plD_esc_ljiip()
492 //
493 // Escape function.
494 //--------------------------------------------------------------------------
495 
496 void
497 plD_esc_ljiip( PLStream *pls, PLINT op, void *ptr )
498 {
499 }
500 
501 //--------------------------------------------------------------------------
502 // setpoint()
503 //
504 // Sets a bit in the bitmap.
505 //--------------------------------------------------------------------------
506 
507 static void
508 setpoint( PLINT x, PLINT y )
509 {
510  PLINT index;
511  index = x / 8 + y * BPROW1;
512  *( bitmap + index ) = *( bitmap + index ) | mask[x % 8];
513 }
514 
515 #else
516 int
518 {
519  return 0;
520 }
521 
522 #endif // PLD_ljii