/* $Id: ljiip.c,v 1.4 2010/10/06 16:02:49 rice Exp $ PLplot Laser Jet IIp device driver. Based on old LJII driver, modifications by Wesley Ebisuzaki DPI = 300, 150, 100 (dots per inch) default: Unix 300 dpi, MS-DOS 150 dpi higher = better output, more memory, longer to print GCMODE = 0, 2 (graphics compression mode) default: 2, old laser jets should use 0 compression can speed up the printing up to 3x */ #include "plDevs.h" #ifdef PLD_ljiip #include "plplotP.h" #include "drivers.h" #include #include #ifdef __GO32__ /* dos386/djgpp */ #ifdef MSDOS #undef MSDOS #endif #endif /* Device info */ const char* plD_DEVICE_INFO_ljiip = /* pmr: const */ "ljiip:LaserJet IIp/deskjet compressed graphics:0:ljiip:32:ljiip"; /* Function prototypes */ /*void plD_dispatch_init_ljiip ( PLDispatchTable *pdt );*/ /* pmr: in drivers.h */ void plD_init_ljiip (PLStream *); void plD_line_ljiip (PLStream *, short, short, short, short); void plD_polyline_ljiip (PLStream *, short *, short *, PLINT); void plD_eop_ljiip (PLStream *); void plD_bop_ljiip (PLStream *); void plD_tidy_ljiip (PLStream *); void plD_state_ljiip (PLStream *, PLINT); void plD_esc_ljiip (PLStream *, PLINT, void *); static void setpoint(PLINT, PLINT); /* top level declarations */ /* GCMODE = graphics compression mode, 0=old laser jets, 2=ljiip or later */ #define GCMODE 2 /* DPI = dots per inch, more dots=better plot, more memory, more time */ /* possible DPI = 75, 100, 150, 300 */ /* if DPI=300 then your machine must have a free 1Mb block of memory */ #define DPI 300 #ifdef MSDOS #undef DPI #define DPI 150 #endif #define OF pls->OutFile #define CURX ((long) (DPI / 5)) #define CURY ((long) (DPI / 7)) #define XDOTS (376 * (DPI / 50)) /* # dots across */ #define YDOTS (500 * (DPI / 50)) /* # dots down */ #define JETX (XDOTS-1) #define JETY (YDOTS-1) #define BPROW (XDOTS/8L) /* # bytes across */ #define MAX_WID 8 /* max pen width in pixels */ #define BPROW1 (BPROW + (MAX_WID+7)/8) /* pen has width, make bitmap bigger */ #define NBYTES BPROW1*(YDOTS+MAX_WID) /* total number of bytes */ /* Graphics control characters. */ #define ESC 0x1b #define FF 0x0c static char mask[8] = {'\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'}; #ifndef MSDOS #define _HUGE #else #define _HUGE _huge #endif static unsigned char _HUGE *bitmap; /* memory area NBYTES in size */ void plD_dispatch_init_ljiip( PLDispatchTable *pdt ) { #ifndef ENABLE_DYNDRIVERS pdt->pl_MenuStr = "LaserJet IIp/deskjet compressed graphics"; pdt->pl_DevName = "ljiip"; #endif pdt->pl_type = plDevType_FileOriented; pdt->pl_seq = 32; pdt->pl_init = (plD_init_fp) plD_init_ljiip; pdt->pl_line = (plD_line_fp) plD_line_ljiip; pdt->pl_polyline = (plD_polyline_fp) plD_polyline_ljiip; pdt->pl_eop = (plD_eop_fp) plD_eop_ljiip; pdt->pl_bop = (plD_bop_fp) plD_bop_ljiip; pdt->pl_tidy = (plD_tidy_fp) plD_tidy_ljiip; pdt->pl_state = (plD_state_fp) plD_state_ljiip; pdt->pl_esc = (plD_esc_fp) plD_esc_ljiip; } /*--------------------------------------------------------------------------*\ * plD_init_ljiip() * * Initialize device. \*--------------------------------------------------------------------------*/ void plD_init_ljiip(PLStream *pls) { PLDev *dev; if (pls->width == 0) /* Is 0 if uninitialized */ pls->width = DPI / 100; /* Initialize family file info */ plFamInit(pls); /* Prompt for a file name if not already set */ plOpenFile(pls); /* Allocate and initialize device-specific data */ dev = plAllocDev(pls); dev->xold = PL_UNDEFINED; dev->yold = PL_UNDEFINED; dev->xmin = 0; dev->ymin = 0; /* number of pixels / mm */ plP_setpxl((PLFLT) (DPI/25.4), (PLFLT) (DPI/25.4)); /* Rotate by 90 degrees since portrait mode addressing is used */ dev->xmin = 0; dev->ymin = 0; dev->xmax = JETY; dev->ymax = JETX; dev->xlen = dev->xmax - dev->xmin; dev->ylen = dev->ymax - dev->ymin; plP_setphy(dev->xmin, dev->xmax, dev->ymin, dev->ymax); /* If portrait mode is specified, then set up an additional rotation * transformation with aspect ratio allowed to adjust via freeaspect. * Default orientation is landscape (ORIENTATION == 3 or 90 deg rotation * counter-clockwise from portrait). (Legacy PLplot used seascape * which was equivalent to ORIENTATION == 1 or 90 deg clockwise rotation * from portrait.) */ if (pls->portrait) { plsdiori((PLFLT)(4 - ORIENTATION)); pls->freeaspect = 1; } /* Allocate storage for bit map matrix */ #ifdef MSDOS if ((bitmap = (unsigned char _HUGE *) halloc((long) NBYTES, sizeof(char))) == NULL) plexit("Out of memory in call to calloc"); #else if ((bitmap = (unsigned char *) calloc(NBYTES, sizeof(char))) == NULL) plexit("Out of memory in call to calloc"); #endif /* Reset Printer */ fprintf(OF, "%cE", ESC); } /*--------------------------------------------------------------------------*\ * plD_line_ljiip() * * Draw a line in the current color from (x1,y1) to (x2,y2). \*--------------------------------------------------------------------------*/ void plD_line_ljiip(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { PLDev *dev = (PLDev *) pls->dev; int xx1 = x1a, yy1 = y1a, xx2 = x2a, yy2 = y2a; int abs_dx, abs_dy, dx, dy, incx, incy; int i, j, width, residual; PLFLT tmp; width = MIN(pls->width, MAX_WID); /* Take mirror image, since PCL expects (0,0) to be at top left */ yy1 = dev->ymax - (yy1 - dev->ymin); yy2 = dev->ymax - (yy2 - dev->ymin); /* Rotate by 90 degrees */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx1, &yy1); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx2, &yy2); dx = xx2 - xx1; dy = yy2 - yy1; if (dx < 0) { abs_dx = -dx; incx = -1; } else { abs_dx = dx; incx = 1; } if (dy < 0) { abs_dy = -dy; incy = -1; } else { abs_dy = dy; incy = 1; } /* make pixel width narrower for diag lines */ if (abs_dy <= abs_dx) { if (abs_dx == 0) tmp = 1.0; else tmp = 1.0 - (PLFLT) abs_dy / abs_dx; } else { tmp = 1.0 - (PLFLT) abs_dx / abs_dy; } width = floor(0.5 + width * (tmp*tmp*tmp*(1.0-0.707107) + 0.707107)); if (width < 1) width = 1; if (width > 1) { for (i = 0; i < width; i++) { for (j = 0; j < width; j++) { setpoint((PLINT) (xx1+i), (PLINT) (yy1+j)); setpoint((PLINT) (xx2+i), (PLINT) (yy2+j)); } } } if (abs_dx >= abs_dy) { residual = -(abs_dx >> 1); if (width == 1) { for (i = 0; i <= abs_dx; i++, xx1 += incx) { setpoint((PLINT) (xx1), (PLINT) (yy1)); if ((residual += abs_dy) >= 0) { residual -= abs_dx; yy1 += incy; } } } else { for (i = 0; i <= abs_dx; i++, xx1 += incx) { for (j = 0; j < width; j++) { setpoint((PLINT) (xx1), (PLINT) (yy1+j)); setpoint((PLINT) (xx1+width-1), (PLINT) (yy1+j)); } if ((residual += abs_dy) >= 0) { residual -= abs_dx; yy1 += incy; } } } } else { residual = -(abs_dy >> 1); if (width == 1) { for (i = 0; i <= abs_dy; i++, yy1 += incy) { setpoint((PLINT) (xx1), (PLINT) (yy1)); if ((residual += abs_dx) >= 0) { residual -= abs_dy; xx1 += incx; } } } else { for (i = 0; i <= abs_dy; i++, yy1 += incy) { for (j = 0; j < width; j++) { setpoint((PLINT) (xx1+j), (PLINT) (yy1)); setpoint((PLINT) (xx1+j), (PLINT) (yy1+width-1)); } if ((residual += abs_dx) >= 0) { residual -= abs_dy; xx1 += incx; } } } } } /*--------------------------------------------------------------------------*\ * plD_polyline_ljiip() * * Draw a polyline in the current color. \*--------------------------------------------------------------------------*/ void plD_polyline_ljiip(PLStream *pls, short *xa, short *ya, PLINT npts) { PLINT i; for (i = 0; i < npts - 1; i++) plD_line_ljiip(pls, xa[i], ya[i], xa[i + 1], ya[i + 1]); } /*--------------------------------------------------------------------------*\ * plD_eop_ljiip() * * End of page.(prints it here). \*--------------------------------------------------------------------------*/ void plD_eop_ljiip(PLStream *pls) { PLINT j; unsigned char _HUGE *p; int iw; #if GCMODE > 0 int i, iy, last, n, jmax; unsigned char _HUGE t_buf[BPROW*2]; unsigned char c; #endif /* PCL III setup: ref. Deskjet Plus Printer Owner's Manual */ fprintf(OF,"\033*rB"); /* end raster graphics */ fprintf(OF,"\033*t%3dR", DPI); /* set DPI */ #if GCMODE != 0 fprintf(OF,"\033*r%dS", XDOTS); /* raster width */ fprintf(OF,"\033*b%1dM", GCMODE); /* graphics mode */ #endif /* First move cursor to origin */ fprintf(OF,"\033*p%ldX", CURX); fprintf(OF,"\033*p%ldY", CURY); fprintf(OF,"\033*r0A"); /* start graphics */ /* Write out raster data */ #if GCMODE == 0 for (j = 0, p = bitmap; j < YDOTS; j++, p += BPROW1) { fprintf(OF,"\033*b>%dW", BPROW); iw = fwrite(p, BPROW, sizeof(char), OF); } #endif #if GCMODE == 2 for (iy = 0, p = bitmap; iy < YDOTS; iy++, p += BPROW1) { /* find last non-zero byte */ last = BPROW - 1; while (last > 0 && p[last] == 0) last--; last++; /* translate to mode 2, save results in t_buf[] */ i = n = 0; while (i < last) { c = p[i]; jmax = i + 127; jmax = last < jmax ? last : jmax; if (i < last - 2 && (c == p[i+1]) && (c == p[i+2])) { j = i + 3; while (j < jmax && c == p[j]) j++; t_buf[n++] = (i-j+1) & 0xff; t_buf[n++] = c; i = j; } else { for (j = i + 1; j < jmax; j++) { if (j < last - 2 && (p[j] == p[j+1]) && (p[j+1] == p[j+2]) ) break; } t_buf[n++] = j - i - 1; while (i < j) { t_buf[n++] = p[i++]; } } } fprintf(OF,"\033*b%dW", (int) n); iw = fwrite(t_buf, (int) n, sizeof(char), OF); } #endif pls->bytecnt += NBYTES; /* End raster graphics and send Form Feed */ fprintf(OF, "\033*rB"); fprintf(OF, "%c", FF); /* Finally, clear out bitmap storage area */ memset((void *) bitmap, '\0', NBYTES); } /*--------------------------------------------------------------------------*\ * plD_bop_ljiip() * * Set up for the next page. * Advance to next family file if necessary (file output). \*--------------------------------------------------------------------------*/ void plD_bop_ljiip(PLStream *pls) { if (!pls->termin) plGetFam(pls); pls->page++; } /*--------------------------------------------------------------------------*\ * plD_tidy_ljiip() * * Close graphics file or otherwise clean up. \*--------------------------------------------------------------------------*/ void plD_tidy_ljiip(PLStream *pls) { /* Reset Printer */ fprintf(OF, "%cE", ESC); fclose(OF); free((char *) bitmap); } /*--------------------------------------------------------------------------*\ * plD_state_ljiip() * * Handle change in PLStream state (color, pen width, fill attribute, etc). \*--------------------------------------------------------------------------*/ void plD_state_ljiip(PLStream *pls, PLINT op) { (void) pls; /* pmr: make these used */ (void) op; } /*--------------------------------------------------------------------------*\ * plD_esc_ljiip() * * Escape function. \*--------------------------------------------------------------------------*/ void plD_esc_ljiip(PLStream *pls, PLINT op, void *ptr) { (void) pls; /* pmr: make these used */ (void) op; (void) ptr; } /*--------------------------------------------------------------------------*\ * setpoint() * * Sets a bit in the bitmap. \*--------------------------------------------------------------------------*/ static void setpoint(PLINT x, PLINT y) { PLINT myindex; myindex = x / 8 + y * BPROW1; *(bitmap + myindex) = *(bitmap + myindex) | mask[x % 8]; } #else int pldummy_ljiip(void) { return 0; } #endif /* PLD_ljii */