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