home *** CD-ROM | disk | FTP | other *** search
- /* $XConsortium: x2jet.c,v 1.5 91/06/26 13:59:00 rws Exp $ */
-
- /* -*-C-*-
- ********************************************************************************
- *
- * File: x2jet.c
- * RCS: x2jet.c,v 1.23 89/07/17 12:02:51 lori Exp
- * Description: xpr support for HP LaserJet and PaintJet printers
- * Author: Larry Rupp, HP Graphics Technology Division
- * Created: Fri Jul 15 15:22:26 1988
- * Modified: Thu Sep 15 11:59:34 1988 (Larry Rupp) ler@hpfcler
- * Tue Dec 6 10:04:43 PST 1988 (Marc Ayotte) marca@hp-pcd
- * Language: C
- * Package: N/A
- * Status: Released to MIT
- *
- * (c) Copyright 1988, Hewlett-Packard Company.
- *
- ********************************************************************************
- */
-
-
-
-
-
- /********************************************************
-
- Copyright (c) 1988 by Hewlett-Packard Company
- Copyright (c) 1988 by the Massachusetts Institute of Technology
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that copyright notice and this permission
- notice appear in supporting documentation, and that the names of
- Hewlett-Packard or M.I.T. not be used in advertising or publicity
- pertaining to distribution of the software without specific, written
- prior permission.
-
- ********************************************************/
-
- #include <stdio.h>
- #include <X11/Xlib.h>
- #include <X11/XWDFile.h>
-
- #include "xpr.h"
-
- #ifdef NLS16
- #ifndef NLS
- #define NLS
- #endif
- #endif
-
- #ifndef NLS
- #define catgets(i, sn,mn,s) (s)
- #else /* NLS */
- #define NL_SETN 2 /* set number */
- #include <nl_types.h>
-
- extern char *catgets();
- extern nl_catd nlmsg_fd;
-
- #endif /* NLS */
-
- #ifndef TRUE
- # define FALSE 0
- # define TRUE 1
- #endif
-
- /* default printable page area (inches) */
- #define STDWIDTH 8.0
- #define STDHEIGHT 10.5
-
- /* header & trailer character cell size (centipoints) */
- #define CHARWIDTH 720
- #define CHARHEIGHT 1200
-
- #define XWDHEADERSIZE (sizeof(XWDFileHeader))
- #define XCOLORSIZE (sizeof(XColor))
-
-
- typedef struct { long width, height; } Area;
- typedef struct { long x, y; } Location;
-
-
- static Area limit; /* image clip limits (dots) */
- static Area page; /* printable page size (centipoints) */
-
- static Location headerloc; /* centipoint location of header string */
- static Location trailerloc; /* centipoint location of trailer string */
- static Location imageloc; /* centipoint location of image */
-
- static int headerlimit; /* number of chars which will printed for */
- static int trailerlimit; /* the image's header/trailer strings */
-
- static XWDFileHeader xwd_header;
-
- static XColor *xwd_colors;
-
- static char *xwd_image;
-
- static unsigned long Z_pixel_mask;
-
- static int true_scale;
-
- extern char *progname;
-
- void fatal_err();
- void fatal_err2();
-
- /* Computes the centipoint width of one printer dot. */
- #define dot_centipoints(s,d) ((7200.0 * s) / d)
-
-
- void set_image_limits (scale, density, orient, print_area)
- int scale, density;
- enum orientation orient;
- Area print_area;
- {
- Area print_dots;
- double dotsize;
-
- /* Set dotsize to the centipoint width of one printer dot. */
- dotsize = dot_centipoints(scale, density);
-
- if (orient == PORTRAIT) {
- print_dots.width = print_area.width / dotsize;
- print_dots.height = print_area.height / dotsize;
- } else {
- print_dots.height = print_area.width / dotsize;
- print_dots.width = print_area.height / dotsize;
- }
-
- limit.width = (print_dots.width < xwd_header.pixmap_width)
- ? print_dots.width : xwd_header.pixmap_width;
- limit.height = (print_dots.height < xwd_header.pixmap_height)
- ? print_dots.height : xwd_header.pixmap_height;
-
- if ((limit.width != xwd_header.pixmap_width)
- || (limit.height != xwd_header.pixmap_height))
- fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,1, "%s: Warning: %ld x %ld image clipped to %ld x %ld.\n")),
- progname,
- xwd_header.pixmap_width, xwd_header.pixmap_height,
- limit.width, limit.height);
- }
-
-
-
- void set_header_trailer_limits (header, trailer, printwidth)
- char *header, *trailer;
- long printwidth;
- {
- /* Determine the number of header and trailer characters
- * that will fit into the available printing area.
- */
- headerlimit = header ? (((strlen(header) * CHARWIDTH) <= printwidth)
- ? strlen(header) : (printwidth / CHARWIDTH))
- : 0;
- if (header && headerlimit != strlen(header)) {
- fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,2,
- "%s: Warning: Header string clipped to %d characters.\n")),
- progname, headerlimit);
- header[headerlimit] = '\0';
- }
-
- trailerlimit = trailer ? (((strlen(trailer) * CHARWIDTH) <= printwidth)
- ? strlen(trailer) : (printwidth / CHARWIDTH))
- : 0;
- if (trailer && trailerlimit != strlen(trailer)) {
- fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,3,
- "%s: Warning: Trailer string clipped to %d characters.\n")),
- progname, trailerlimit);
- trailer[headerlimit] = '\0';
- }
- }
-
-
- void set_print_locations (scale, density, top, left,
- header, trailer, orient, position_on_page)
- int scale, density;
- int top, left;
- char *header, *trailer;
- enum orientation orient;
- int position_on_page;
- {
- Area image;
- double dotsize;
-
- /* Set dotsize to the centipoint width of one printer dot. */
- dotsize = dot_centipoints(scale, density);
-
- /* Compute the centipoint size of the clipped image area. */
- if (orient == PORTRAIT) {
- image.width = limit.width * dotsize;
- image.height = limit.height * dotsize;
- } else {
- image.height = limit.width * dotsize;
- image.width = limit.height * dotsize;
- }
-
- if (position_on_page) {
- /* set vertical positions */
- imageloc.y = (top >= 0)
- ? top * 24 + ((header) ? CHARHEIGHT : 0)
- : ((page.height - ((header) ? CHARHEIGHT : 0)
- - image.height - ((trailer) ? CHARHEIGHT : 0)) / 2)
- + ((header) ? CHARHEIGHT : 0);
- headerloc.y = imageloc.y - CHARHEIGHT / 4;
- trailerloc.y = imageloc.y + image.height + (3 * CHARHEIGHT) / 4;
-
- /* set horizontal positions */
- if (left >= 0)
- headerloc.x = imageloc.x = trailerloc.x = left * 24;
- else {
- headerloc.x = (page.width - headerlimit * CHARWIDTH) / 2;
- imageloc.x = (page.width - image.width) / 2;
- trailerloc.x = (page.width - trailerlimit * CHARWIDTH) / 2;
- }
- }
- }
-
-
- int scale_raster (density, orient, print_area)
- int density;
- enum orientation orient;
- Area print_area;
- {
- Area image;
- int h_scale, v_scale;
-
- /* Set the image dimensions to the number of centipoints that would be
- * required for printing at the selected density.
- */
- if (orient == PORTRAIT) {
- image.width = xwd_header.pixmap_width * 7200 / density;
- image.height = xwd_header.pixmap_height * 7200 / density;
- } else {
- image.height = xwd_header.pixmap_width * 7200 / density;
- image.width = xwd_header.pixmap_height * 7200 / density;
- }
-
- /* Calculate the maximum image multiplier along
- * the horizontal and vertical dimensions.
- */
- h_scale = print_area.width / image.width;
- v_scale = print_area.height / image.height;
-
- /* If the image can be expanded, return the lesser of the horizontal and
- * vertical multipliers. Otherwise, the image will not completely fit
- * the available print area, so just return 1 as the expansion factor.
- */
- return (((h_scale > 0) && (v_scale > 0))
- ? ((h_scale<v_scale) ? h_scale : v_scale)
- : 1);
- }
-
-
- scale_and_orient_image (scale, density, width, height, left, top,
- header, trailer,
- orient, position_on_page, device)
- int *scale, *density;
- int width, height, left, top; /* in 300ths of an inch */
- char *header, *trailer;
- enum orientation *orient;
- int position_on_page;
- enum device device;
- {
- Area usable;
-
- /* Determine printable area expressed in centipoints. There are 7200
- * centipoints to the inch. The width and height parameters passed in
- * are expressed in 300ths of an inch, therefore a 24x conversion factor
- * is used on the parameter values. The default page dimensions STDWIDTH
- * and STDHEIGHT are expressed in inches so must be multiplied by 7200
- * to convert to centipoints.
- */
- page.width = (width >= 0) ? width * 24 : STDWIDTH * 7200;
- page.height = (height >= 0) ? height * 24 : STDHEIGHT * 7200;
-
- /* Paintjet Xl has a mechanical form feed, not a strip feed. It has
- * a slop of about 1/4 to 1/2 of an inch at the top and bottom.
- * deduct it from the page height.
- */
- if (device == PJETXL)
- page.height = page.height - 7200;
-
- /* Determine the area usable for the image. This area will be smaller
- * than the total printable area if margins or header/trailer strings
- * have been specified. Margins, like width and height discussed above,
- * are expressed in 300ths of an inch and must be converted to centipoints.
- * Header and trailer strings each reduce the available image height
- * by 1/6 inch, or 1200 centipoints (aka CHARHEIGHT).
- */
- usable.width = page.width - ((left > 0) ? (left * 24) : 0);
- usable.height = page.height - ((top > 0) ? (top * 24) : 0)
- - ((header) ? CHARHEIGHT : 0)
- - ((trailer) ? CHARHEIGHT : 0);
-
- /* Quit here if there is no usable image space. */
- if ((usable.width <= 0) || (usable.height <= 0)) {
- fatal_err((catgets(nlmsg_fd,NL_SETN,4,
- "No space available on page for image.")));
- }
-
- /* Determine image orientation. The orientation will only be changed if
- * it was not specified by a command line option. Portrait mode will be
- * used if either the usable printing area or the image area are square.
- * Portrait mode will also be used if the long dimensions of the usable
- * printing area and the image area match, otherwise landscape mode is
- * used. Portrait mode really means "don't rotate" and landscape mode
- * means "rotate".
- */
- if (*orient == UNSPECIFIED) {
- if ((usable.width == usable.height)
- || (xwd_header.pixmap_width == xwd_header.pixmap_height))
- *orient = PORTRAIT;
- else
- *orient = ((usable.width < usable.height)
- == (xwd_header.pixmap_width < xwd_header.pixmap_height))
- ? PORTRAIT : LANDSCAPE;
- }
-
- /* Set the dots-per-inch print density if it was not specified */
- if (*density <= 0) {
- switch(device) {
- case LJET: *density = 300;
- break;
- case PJET: *density = 90;
- break;
- case PJETXL: *density = 180;
- break;
- }
- }
-
- /* Fit image to available area if scale was not specified */
- if (*scale <= 0)
- *scale = scale_raster(*density, *orient, usable);
-
- /* Determine image clipping limits */
- set_image_limits(*scale, *density, *orient, usable);
-
- /* Determine header/trailer string length clipping */
- set_header_trailer_limits(header, trailer, usable.width);
-
- /* Calculate locations for page layout */
- set_print_locations(*scale, *density, top, left,
- header, trailer, *orient, position_on_page);
-
- }
-
-
- unsigned short fullintensity;
-
- #define BLACK 1
- #define WHITE 0
- #define EMPTY -1
- #define MAX_PJ_COLOR 16
-
- #define RGBmatch(r,g,b,i) (r == i) && (g == i) && (b == i)
-
-
- /* Colormap array is used to map from the Xcolor array (xwd_colors) index
- * numbers into a pjcolor index number. This style of mapping is done when
- * interpreting non-Direct/TrueColor visual types.
- */
- long *colormap;
-
-
- /* Pjcolor array is used to hold the scaled RGB triple values
- * programmed into the printer.
- */
- long pjcolor[MAX_PJ_COLOR];
-
-
- static int color_warning_given = FALSE;
-
-
- /* Global visual type indicator, used to select color interpretation method. */
- char Direct_or_TrueColor;
-
-
- typedef struct {
- unsigned long Rmask, Gmask, Bmask;
- int Rshift, Gshift, Bshift;
- } RGBshiftmask;
-
-
- /* Color index element definition, these are linked into a circular list
- * for interpretation of DirectColor or TrueColor visual types.
- */
- typedef struct colorindex {
- long index;
- long pjcolor_index;
- struct colorindex *next;
- } COLORINDEX;
-
-
- /* Global data for color interpretation. This structure serves as a home
- * for the color index lists (only used when processing DirectColor or
- * TrueColor visual types). It also holds color processing switches and a
- * pointer to the output file to reduce parameter passing overhead.
- */
- struct {
- int PaintJet;
- int Invert;
- unsigned int CutOff;
- FILE *OutFile;
- COLORINDEX *indexchain, *freechain;
- RGBshiftmask sm;
- } color;
-
-
- void setup_RGBshiftmask (sm, rmask, gmask, bmask)
- RGBshiftmask *sm;
- unsigned long rmask, gmask, bmask;
- {
- sm->Rmask = rmask; sm->Gmask = gmask; sm->Bmask = bmask;
- sm->Rshift = 0; sm->Gshift = 0; sm->Bshift = 0;
-
- if (!rmask)
- fatal_err((catgets(nlmsg_fd,NL_SETN,5, "red mask for visual is zero.")));
- if (!gmask)
- fatal_err((catgets(nlmsg_fd,NL_SETN,6, "green mask for visual is zero.")));
- if (!bmask)
- fatal_err((catgets(nlmsg_fd,NL_SETN,7, "blue mask for visual is zero.")));
-
- for (; !(rmask & 1); sm->Rshift++)
- rmask >>= 1;
- for (; !(gmask & 1); sm->Gshift++)
- gmask >>= 1;
- for (; !(bmask & 1); sm->Bshift++)
- bmask >>= 1;
- }
-
-
-
- void swap_black_and_white ()
- {
- /* Reverse black and white in the Xcolor structure array. */
-
- XColor *color;
- int n;
-
- for (n=xwd_header.ncolors, color=xwd_colors; n>0; n--, color++)
- if (RGBmatch((color->red & fullintensity), (color->green & fullintensity),
- (color->blue & fullintensity), fullintensity))
- color->red = color->green = color->blue = 0;
- else if (RGBmatch(color->red, color->green, color->blue, 0))
- color->red = color->green = color->blue = fullintensity;
- }
-
-
- void reset_color_mapping ()
- {
- int n;
- long *cmap;
- COLORINDEX *splice;
-
- for (n=0; n<MAX_PJ_COLOR; n++)
- pjcolor[n] = EMPTY;
-
- if (!color.PaintJet) {
- /* preload for monochrome output */
- pjcolor[0] = WHITE;
- pjcolor[1] = BLACK;
- }
-
- if (Direct_or_TrueColor) {
- /* move color index chain cells onto the free list */
- if (color.indexchain != NULL) {
- splice = color.indexchain->next;
- color.indexchain->next = color.freechain;
- color.freechain = splice;
- color.indexchain = NULL;
- }
- } else if (color.PaintJet)
- for (n=xwd_header.ncolors, cmap=colormap; n>0; n--, cmap++)
- *cmap = EMPTY;
- }
-
-
- #define Intensity(r,g,b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
-
-
- void prepare_color_mapping (invert, paintjet, cutoff, out)
- int invert, paintjet;
- unsigned int cutoff;
- FILE *out;
- {
- int n;
- long *cmap;
- XColor *xcolor;
-
- for (n = xwd_header.bits_per_rgb, fullintensity = 0; n > 0; n--)
- fullintensity = (fullintensity << 1) | 1;
- for (n = sizeof(short) * 8 - xwd_header.bits_per_rgb; n > 0; n--)
- fullintensity = (fullintensity << 1);
-
- Direct_or_TrueColor = (xwd_header.visual_class == DirectColor
- || xwd_header.visual_class == TrueColor);
- color.PaintJet = paintjet;
- color.Invert = invert;
- color.CutOff = cutoff;
- color.OutFile = out;
- color.indexchain = NULL;
- color.freechain = NULL;
-
- if (Direct_or_TrueColor)
- setup_RGBshiftmask(&color.sm, xwd_header.red_mask,
- xwd_header.green_mask, xwd_header.blue_mask);
- else {
- if (!(colormap = (long *) malloc(xwd_header.ncolors * sizeof(long))))
- fatal_err((catgets(nlmsg_fd,NL_SETN,24,
- "Could not allocate memory for X-to-printer colormap.")));
-
- /* For PaintJet, color map assignment will be done one line at a time.
- * So for now just interchange the Xcolor structure's black and white
- * if the -rv command line option was specified.
- */
- if (paintjet && invert)
- swap_black_and_white();
-
- /* For LaserJet, map each color to black or white based upon the
- * combined intensity of the RGB components. Note that the normal
- * non-reversed (-rv) LaserJet mapping will represent light areas
- * of the screen as black on the paper.
- */
- if (!paintjet)
- for (n=xwd_header.ncolors, xcolor=xwd_colors, cmap=colormap; n>0;
- n--, xcolor++, cmap++)
- *cmap = (Intensity(xcolor->red, xcolor->green, xcolor->blue) < cutoff)
- ? (invert ? BLACK : WHITE)
- : (invert ? WHITE : BLACK);
- }
- reset_color_mapping();
- }
-
-
- /* On a PaintJet printer, the programmable color intensity ranges are:
- *
- * red: 4..90 green: 4..88 blue: 6..85
- *
- * The following macros map the 0..65535 intensity ranges of X colors
- * into the PaintJet's ranges.
- */
-
- #define fixred(x) (x / 762 + 4)
- #define fixgreen(x) (x / 780 + 4)
- #define fixblue(x) (x / 829 + 6)
-
- #define is_grey(r,g,b) ((r == g) && (r == b))
-
-
-
- void select_grey (level, r, g, b)
- int level, *r, *g, *b;
- {
- /* Forced selection of a grey. This is done since the PaintJet does
- * not do very well when picking greys, they tend to become pink!
- */
- if (level > 66) { /* white */
- *r = 90; *g = 88; *b = 85;
- } else if (level > 35) {
- *r = 43; *g = 43; *b = 45;
- } else if (level > 21) {
- *r = 25; *g = 25; *b = 33;
- } else if (level > 15) {
- *r = 15; *g = 16; *b = 18;
- } else if (level > 11) {
- *r = 14; *g = 14; *b = 18;
- } else if (level > 6) {
- *r = 6; *g = 7; *b = 8;
- } else { /* black */
- *r = 4; *g = 4; *b = 6;
- }
- }
-
-
- long find_nearest_programmed_color ();
-
- int load_printer_color (index, nearmatch, device) /* for non Direct/TrueColor */
- long index;
- int nearmatch;
- enum device device;
- {
- int n, red, blue, green, xred, xgreen, xblue;
- long compositeRGB;
-
- if (colormap[index] != EMPTY)
- /* printer has already been programmed for this color index */
- return(1); /* "success" */
- else {
- xred = xwd_colors[index].red;
- xgreen = xwd_colors[index].green;
- xblue = xwd_colors[index].blue;
- /* determine the scaled RGB PaintJet color values */
- if (device == PJET) {
- red = fixred(xred);
- green = fixgreen(xgreen);
- blue = fixblue(xblue);
- if (is_grey(xred, xgreen, xblue)) /* assist grey selection */
- select_grey(red, &red, &green, &blue);
- }
- compositeRGB = (red << 16) | (green << 8) | blue;
- /* search for a matching or unused PaintJet mapping entry */
- for (n=0; n<MAX_PJ_COLOR; n++) {
- if (pjcolor[n] == compositeRGB) {
- /* record mapping for this index */
- colormap[index] = n;
- /* return "success" */
- return(1);
- } else if (pjcolor[n] == EMPTY) {
- /* download color to printer */
- fprintf(color.OutFile,"\033*v%dA", red);
- fprintf(color.OutFile,"\033*v%dB", green);
- fprintf(color.OutFile,"\033*v%dC", blue);
- fprintf(color.OutFile,"\033*v%dI", n);
- /* record that this is now programmed */
- pjcolor[n] = compositeRGB;
- colormap[index] = n;
- /* return "success" */
- return(1);
- }
- }
- /* unable to find or program this color */
- if (nearmatch)
- colormap[index] = find_nearest_programmed_color(compositeRGB);
- }
- return(0); /* "failure" */
- }
-
-
- /* Lookup the image color index on the color.indexchain list. If found
- * return the corresponding printer color index, otherwise -1. The index
- * chain is a singly linked circular list. Its head pointer is left at
- * the last cell matched on the theory that this will allow faster lookup
- * for runs of color.
- */
- int lookup_color_index (i)
- long i;
- {
- COLORINDEX *start, *current;
-
- start = current = color.indexchain;
-
- if (current == NULL)
- return(-1); /* not found */
-
- do {
- if (current->index == i) {
- color.indexchain = current;
- return(current->pjcolor_index); /* found */
- }
- current = current->next;
- } while (current != start);
-
- return(-1); /* not found */
- }
-
-
- /* Calculate the individual and composite printer RGB values. (Only the
- * composite value is set for monochrome output.)
- */
- void select_printer_color (index, red, green, blue, compositeRGB, device)
- long index;
- int *red, *green, *blue;
- long *compositeRGB;
- enum device device;
- {
- int xred, xgreen, xblue;
-
- xred = xwd_colors[((index & color.sm.Rmask) >> color.sm.Rshift)].red;
- xgreen = xwd_colors[((index & color.sm.Gmask) >> color.sm.Gshift)].green;
- xblue = xwd_colors[((index & color.sm.Bmask) >> color.sm.Bshift)].blue;
-
- if (color.PaintJet) {
- if (color.Invert) {
- if (RGBmatch((xred & fullintensity), (xgreen & fullintensity),
- (xblue & fullintensity), fullintensity))
- xred = xgreen = xblue = 0;
- else if (RGBmatch(xred, xgreen, xblue, 0))
- xred = xgreen = xblue = fullintensity;
- }
- /* determine the scaled RGB PaintJet color values */
- if (device == PJET) {
- *red = fixred(xred);
- *green = fixgreen(xgreen);
- *blue = fixblue(xblue);
- if (is_grey(xred, xgreen, xblue)) /* assist grey selection */
- select_grey(*red, red, green, blue);
- }
- if (device == PJETXL) {
- *red = xred >> 8;
- *green = xgreen >> 8;
- *blue = xblue >> 8;
- }
- *compositeRGB = (*red << 16) | (*green << 8) | *blue;
- } else /* monochrome */
- *compositeRGB = (Intensity(xred, xgreen, xblue) < color.CutOff)
- ? (color.Invert ? BLACK : WHITE)
- : (color.Invert ? WHITE : BLACK);
- }
-
-
-
- /* Search for a color matching the compositeRGB value in the array of
- * colors already programmed into the printer. Returns 1 if found,
- * 0 otherwise. The matching array index is returned in pindex.
- */
- int color_already_in_printer (compositeRGB, pindex)
- long compositeRGB, *pindex;
- {
- int n;
-
- for (n=0; n<MAX_PJ_COLOR; n++)
- if (pjcolor[n] == EMPTY)
- return(0); /* not found */
- else if (pjcolor[n] == compositeRGB) {
- *pindex = n;
- return(1); /* found */
- }
- return(0); /* not found */
- }
-
-
- int program_new_printer_color (red, green, blue, compositeRGB, pindex)
- int red, green, blue;
- long compositeRGB;
- long *pindex;
- {
- int n;
-
- for (n=0; n<MAX_PJ_COLOR; n++)
- if (pjcolor[n] == EMPTY) {
- /* download color to printer */
- fprintf(color.OutFile,"\033*v%dA", red);
- fprintf(color.OutFile,"\033*v%dB", green);
- fprintf(color.OutFile,"\033*v%dC", blue);
- fprintf(color.OutFile,"\033*v%dI", n);
- /* record that this is now programmed */
- pjcolor[n] = compositeRGB;
- *pindex = n;
- /* return "success" */
- return(1);
- }
- /* unable to program this color, return "failure" */
- return(0);
- }
-
-
-
- long composite_diff (x, y)
- long x, y;
- {
- long r = (x >> 16 & 0xFF) - (y >> 16 & 0xFF);
- long g = (x >> 8 & 0xFF) - (y >> 8 & 0xFF);
- long b = (x & 0xFF) - (y & 0xFF);
-
- return(r*r + g*g + b*b);
- }
-
-
-
- long find_nearest_programmed_color (compositeRGB)
- long compositeRGB;
- {
- int n, nearest = 0;
- long neardiff = composite_diff(pjcolor[0], compositeRGB);
- long diff;
-
- for (n=1; n<MAX_PJ_COLOR; n++) {
- diff = composite_diff(pjcolor[n], compositeRGB);
- if (diff < neardiff) {
- neardiff = diff;
- nearest = n;
- }
- }
- return(nearest);
- }
-
-
- void add_index_to_chain (cindex, pindex)
- long cindex;
- long pindex;
- {
- COLORINDEX *new;
-
- /* Get a new cell for the color index chain. Take it from the free list
- * if possible, otherwise malloc space.
- */
- if (color.freechain == NULL) {
- if (!(new = (COLORINDEX *) malloc(sizeof(COLORINDEX))))
- fatal_err((catgets(nlmsg_fd,NL_SETN,8,
- "Could not allocate memory for color translation.")));
- } else {
- new = color.freechain;
- color.freechain = color.freechain->next;
- }
-
- /* put index values in the new cell */
- new->index = cindex;
- new->pjcolor_index = pindex;
-
- /* link the new cell into the chain */
- if (color.indexchain == NULL)
- new->next = new;
- else {
- new->next = color.indexchain->next;
- color.indexchain->next = new;
- }
- /* leave head pointer at the new cell */
- color.indexchain = new;
- }
-
-
-
- int load_printer_color_DT (index, nearmatch, device) /* for Direct/TrueColor */
- long index;
- int nearmatch;
- enum device device;
- {
- int pjred, pjgreen, pjblue;
- long compositeRGB;
- long pindex;
-
- if (lookup_color_index(index) >= 0)
- return(1); /* "success" */
- else {
- select_printer_color(index, &pjred, &pjgreen, &pjblue, &compositeRGB,
- device);
- if (color_already_in_printer(compositeRGB, &pindex)) {
- add_index_to_chain(index, pindex);
- return(1); /* success */
- } else if (program_new_printer_color(pjred, pjgreen, pjblue,
- compositeRGB, &pindex)) {
- add_index_to_chain(index, pindex);
- return(1); /* success */
- } else if (nearmatch) {
- add_index_to_chain(index, find_nearest_programmed_color(compositeRGB));
- return(0); /* failure, sorta... */
- }
- }
- return(0); /* failure */
- }
-
-
- int load_line_colors (line, length, nearmatch, device)
- long *line;
- int length, nearmatch;
- enum device device;
- {
- int result = 1; /* initialized to "success" */
-
- for (; length>0; length--, line++) {
- result &= Direct_or_TrueColor
- ? load_printer_color_DT(*line, nearmatch, device)
- : load_printer_color(*line, nearmatch, device);
- if (!(nearmatch || result))
- break;
- }
- return(result);
- }
-
-
-
- void download_colors (line, length, device)
- long *line;
- int length;
- enum device device;
- {
- /* For the first attempt at loading the colors for a line only exact
- * color matches are accepted. If this fails, the closest colors are
- * accepted on the second attempt.
- *
- * Note: The first "if" test below bypasses the initial color loading
- * attempt for monochrome output (which will only come here for Direct
- * or TrueColor mono). This forces reset_color_mapping which is
- * necessary to keep the color index chain down to a tolerable length.
- */
- if (!color.PaintJet || !load_line_colors(line, length, FALSE, device)) {
- reset_color_mapping();
- if (!load_line_colors(line, length, TRUE, device) &&
- !color_warning_given) {
- fprintf(stderr,(catgets(nlmsg_fd,NL_SETN,9,
- "%s: Warning: Cannot print all image colors.\n")),
- progname);
- color_warning_given = TRUE;
- }
- }
- }
-
-
- void validate_visual()
- {
- int depth = xwd_header.pixmap_depth;
- char *errmsg = catgets(nlmsg_fd,NL_SETN,25,
- "%d bit deep %s bitmap not supported.\n");
-
- switch (xwd_header.visual_class) {
- case GrayScale:
- if (depth > 8) fatal_err2(errmsg, depth, "GrayScale"); break;
- case StaticGray:
- if (depth > 8) fatal_err2(errmsg, depth, "StaticGray"); break;
- case PseudoColor:
- if (depth > 8) fatal_err2(errmsg, depth, "PseudoColor"); break;
- case StaticColor:
- if (depth > 8) fatal_err2(errmsg, depth, "StaticColor"); break;
- case DirectColor:
- case TrueColor:
- if (depth != 12 && depth != 24)
- fatal_err2(errmsg, depth, (xwd_header.visual_class == DirectColor)
- ? "DirectColor" : "TrueColor");
- break;
- default:
- fatal_err2((catgets(nlmsg_fd,NL_SETN,26,
- "visual class #%d not supported.\n")), xwd_header.visual_class);
- }
- }
-
- void read_xwd_data (in)
- FILE *in;
- {
- # define WINDOW_NAME_ALLOC 32
- unsigned long swaptest = 1;
- int window_name_size;
- int image_size;
- int n;
- char window_name [WINDOW_NAME_ALLOC];
-
- /* Read in XWDFileHeader structure */
- if (fread((char*) &xwd_header, 1, XWDHEADERSIZE, in) != XWDHEADERSIZE)
- fatal_err((catgets(nlmsg_fd,NL_SETN,10,
- "Could not read xwd file's header.")));
-
- if (*(char *) &swaptest)
- _swaplong((char *) &xwd_header, XWDHEADERSIZE);
-
- validate_visual();
-
- /* Skip over window name */
- window_name_size = xwd_header.header_size - XWDHEADERSIZE;
- while (window_name_size > 0) {
- n = window_name_size > WINDOW_NAME_ALLOC
- ? WINDOW_NAME_ALLOC : window_name_size;
- if (fread(window_name, 1, n, in) != n)
- fatal_err((catgets(nlmsg_fd,NL_SETN,11,
- "Could not read xwd file's window name.")));
- window_name_size -= n;
- }
-
- /* Allocate space for xwd color structures */
- if (!(xwd_colors = (XColor*) malloc(sizeof(XColor) * xwd_header.ncolors)))
- fatal_err((catgets(nlmsg_fd,NL_SETN,12,
- "Could not allocate memory for xwdfile color table.")));
-
- /* Read in xwd color structures */
- for (n = 0; n < xwd_header.ncolors; n++)
- if (fread(&xwd_colors[n], 1, XCOLORSIZE, in) != XCOLORSIZE)
- fatal_err((catgets(nlmsg_fd,NL_SETN,13,
- "Could not read xwd file's color table.")));
-
- if (*(char *) &swaptest) {
- for (n = 0; n < xwd_header.ncolors; n++) {
- _swaplong((char *) &xwd_colors[n].pixel, sizeof(long));
- _swapshort((char *) &xwd_colors[n].red, 3 * sizeof(short));
- }
- }
-
- /* Allocate space for xwd image */
- if (xwd_header.pixmap_format == ZPixmap)
- image_size = 1;
- else if (xwd_header.pixmap_format == XYPixmap)
- image_size = xwd_header.pixmap_depth;
- else
- fatal_err((catgets(nlmsg_fd,NL_SETN,14,
- "Image in xwd file is not in Z or XY pixmap format.")));
- image_size *= xwd_header.bytes_per_line * xwd_header.pixmap_height;
- if (!(xwd_image = malloc(image_size)))
- fatal_err((catgets(nlmsg_fd,NL_SETN,15,
- "Could not allocate memory for xwd file's image.")));
-
- /* Read in xwd image */
- if (fread(xwd_image, 1, image_size, in) != image_size)
- fatal_err((catgets(nlmsg_fd,NL_SETN,16,
- "Could not read xwd file's image.")));
-
- }
-
-
- write_image_prefix (out, scale, density, header, device, position_on_page,
- initial_formfeed, orient, gamma, render, slide)
- FILE *out;
- int scale, density;
- char *header;
- enum device device;
- int position_on_page, initial_formfeed;
- enum orientation orient;
- float gamma;
- int render;
- int slide;
- {
- if (initial_formfeed)
- fprintf(out,"\014");
-
- /* Write out header & positioning commands */
- if (header) {
- if (position_on_page)
- fprintf(out,"\033&a%dH\033&a%dV",
- /* headerloc x & y are written in decipoints */
- (int) headerloc.x / 10, (int) headerloc.y / 10);
- fprintf(out,"%s\n", header);
- }
-
- /* Prepare printer for raster graphics: */
-
- /* Write image positioning commands */
- if (position_on_page)
- fprintf(out,"\033&a%dH\033&a%dV",
- /* imageloc x & y are written in decipoints */
- (int) imageloc.x / 10, (int) imageloc.y / 10);
-
- /* If doing transparencies, tell the printer before raster graphics */
- if (slide && device != LJET)
- fprintf(out, "\033&k3W");
-
- /* Set printer resolution */
- fprintf(out,"\033*t%dR", density);
-
- /*
- * do device dependent escape sequences
- */
- if (device == PJET) {
- /* Enable all four "planes" for PaintJet */
- fprintf(out,"\033*r4U");
-
- /* Set picture width for PaintJet */
- fprintf(out,"\033*r%dS",
- ((int) (orient == PORTRAIT) ? limit.width : limit.height)
- * scale);
- }
-
- /* Enable various options for PaintJet XL */
- if (device == PJETXL) {
- double dotsize;
- int n;
-
- /* Speed up printing by telling that there
- * will be no negative positioning
- */
- fprintf(out, "\033&a1N");
-
- if (gamma > 0.009)
- fprintf(out, "\033*t%.2fI", gamma);
-
- if (render > 0)
- fprintf(out, "\033*t%dJ", render);
-
- if (Direct_or_TrueColor)
- /* Enable direct by pixel for PaintJet XL */
- fwrite("\033*v6W\000\003\010\010\010\010", 1, 11, out);
- else {
- /* Enable index by pixel for PaintJet XL */
- fwrite("\033*v6W\000\001\010\010\010\010", 1, 11, out);
-
- /* Program the palette */
- for (n = 0; n < xwd_header.ncolors; n++) {
- fprintf(out,"\033*v%dA", (xwd_colors[n].red >> 8));
- fprintf(out,"\033*v%dB", (xwd_colors[n].green >> 8));
- fprintf(out,"\033*v%dC", (xwd_colors[n].blue >> 8));
- fprintf(out,"\033*v%dI", n);
- }
- }
-
- /****************************************
- * *
- * PaintJet XL will do its own scaling *
- * *
- * Set picture width for PaintJet XL *
- ****************************************/
- fprintf(out,"\033*r%dS",
- ((int) (orient == PORTRAIT) ? xwd_header.pixmap_width
- : xwd_header.pixmap_height));
- fprintf(out,"\033*r%dT",
- ((int) (orient == PORTRAIT) ? xwd_header.pixmap_height
- : xwd_header.pixmap_width));
-
- dotsize = dot_centipoints(scale, density);
-
- fprintf(out,"\033*t%dH",
- (int)(((orient == PORTRAIT) ? xwd_header.pixmap_width
- : xwd_header.pixmap_height)
- * dotsize / 10));
-
- fprintf(out,"\033*t%dV",
- (int)(((orient == PORTRAIT) ? xwd_header.pixmap_height
- : xwd_header.pixmap_width)
- * dotsize / 10));
- }
-
- /* Switch to raster graphics mode */
- if (device != PJETXL)
- fprintf(out,"\033*r1A");
- else
- fprintf(out,"\033*r3A");
-
- }
-
-
- write_image_suffix (out, trailer, position_on_page, slide, render, device)
- FILE *out;
- char *trailer;
- int position_on_page;
- int slide, render;
- enum device device;
- {
- /* Exit raster graphics mode */
- if (device == PJETXL)
- fprintf(out,"\033*rC");
- else
- fprintf(out,"\033*rB");
-
- /* If doing transparencies, tell it to stop */
- if (slide && device != LJET)
- fprintf(out, "\033&k1W");
-
- if (device == PJETXL) {
- /* If selected a rendering algorithm, tell it to stop */
- if (render)
- fprintf(out, "\033*t3J");
- fprintf(out, "\033&a0N");
- }
-
- /* Write out trailer & positioning commands */
- if (trailer) {
- if (position_on_page)
- fprintf(out,"\033&a%dH\033&a%dV",
- /* trailerloc x & y are written in decipoints */
- (int) trailerloc.x / 10, (int) trailerloc.y / 10);
- fprintf(out,"%s\n", trailer);
- }
- }
-
-
- unsigned long Z_image_pixel (x, y)
- int x, y;
- {
- int pixel_bytes, offset;
- unsigned char *image;
- unsigned long pixel;
-
- pixel_bytes = xwd_header.bits_per_pixel >> 3;
- offset = ((xwd_header.bits_per_pixel == 4) ? (x / 2)
- : ((xwd_header.bits_per_pixel == 1) ? (x / 8)
- : (x * pixel_bytes)))
- + (y * xwd_header.bytes_per_line);
-
- image = (unsigned char *) &xwd_image[offset];
-
- switch (pixel_bytes) {
- case 0: /* pixel per nibble or bit per pixel packing */
- if (xwd_header.bits_per_pixel == 1) {
- if (xwd_header.byte_order == MSBFirst)
- pixel = *image >> (7 - (x % 8));
- else
- pixel = *image >> (x % 8);
- } else { /* xwd_header.bits_per_pixel == 4 */
- if (xwd_header.byte_order == MSBFirst)
- pixel = (x & 1) ? *image : (*image >> 4);
- else
- pixel = (x & 1) ? (*image >> 4) : *image;
- }
- break;
- case 1:
- pixel = *image;
- break;
- case 2:
- pixel = (xwd_header.byte_order == MSBFirst)
- ? ((unsigned long)*image << 8 | *(image + 1))
- : (*image | (unsigned long)*(image + 1) << 8);
- break;
- case 3:
- pixel = (xwd_header.byte_order == MSBFirst)
- ? ((unsigned long)*image << 16 |
- (unsigned long)*(image + 1) << 8 |
- (unsigned long)*(image + 2))
- : (*image |
- (unsigned long)*(image + 1) << 8 |
- (unsigned long)*(image + 2) << 16);
- break;
- case 4:
- pixel = (xwd_header.byte_order == MSBFirst)
- ? ((unsigned long)*image << 24 |
- (unsigned long)*(image+1) << 16 |
- (unsigned long)*(image+2) << 8 |
- *(image+3))
- : (*image |
- (unsigned long)*(image+1) << 8 |
- (unsigned long)*(image+2) << 16 |
- (unsigned long)*(image+3) << 24);
- break;
- }
- return (pixel & Z_pixel_mask);
- }
-
-
- unsigned long XY_image_pixel (x, y)
- int x, y;
- {
- int plane_start, line_start, bytes_per_bitmap_unit, bitmap_unit_start,
- byte_within_bitmap_unit, offset, byte_mask;
-
- plane_start = (xwd_header.pixmap_depth - 1) * xwd_header.pixmap_height
- * xwd_header.bytes_per_line;
- line_start = xwd_header.bytes_per_line * y;
- bytes_per_bitmap_unit = xwd_header.bitmap_unit >> 3;
- bitmap_unit_start = (x / xwd_header.bitmap_unit) * bytes_per_bitmap_unit;
- byte_within_bitmap_unit = (xwd_header.byte_order == MSBFirst)
- ? (x % xwd_header.bitmap_unit) >> 3
- : bytes_per_bitmap_unit - ((x % xwd_header.bitmap_unit) >> 3) - 1;
-
- offset = plane_start + line_start + bitmap_unit_start
- + byte_within_bitmap_unit;
-
- byte_mask = (xwd_header.bitmap_bit_order == MSBFirst)
- ? 0x80 >> (x % 8) : 0x01 << (x % 8);
-
- return(xwd_image[offset] & byte_mask ? 1 : 0);
- }
-
-
- void direct_by_pixel(out, line, length, device)
- FILE *out;
- long *line;
- int length;
- enum device device;
- {
- int red, green, blue;
- long compositeRGB;
-
- fprintf(out, "\033*b%dW", length * 3);
- for (; length>0; length--, line++) {
- select_printer_color(*line, &red, &green, &blue, &compositeRGB, device);
- fprintf(out, "%c%c%c", (char) red, (char) green, (char) blue);
- }
- }
-
-
- void index_by_pixel(out, line, length)
- FILE *out;
- long *line;
- int length;
- {
- register int n;
- long *lp;
- char *line_pixels;
- register char *lc;
-
- if (!(line_pixels = malloc(length)))
- fatal_err((catgets(nlmsg_fd,NL_SETN,17,
- "Could not allocate raster line memory.")));
-
- for (n=0, lc=line_pixels, lp=line; n<length; n++)
- *lc++ = (char) *lp++;
-
- fprintf(out, "\033*b%dW", length);
- fwrite(line_pixels, 1, length, out);
-
- free(line_pixels);
- }
-
-
- void write_raster_line (out, scale, device, line, length)
- FILE *out;
- int scale;
- enum device device;
- long *line;
- int length;
- {
- int planes = (device == PJET) ? 4 : 1;
- int raster_bytes = (length * scale + 7) / 8;
- register int bytebits, n, p, e, bit;
- long *lp;
- char *line_colors, *raster_line;
- register char *lc, *rl, byte = 0;
-
- if (device == PJETXL) {
- if (Direct_or_TrueColor)
- direct_by_pixel(out, line, length, device);
- else
- index_by_pixel(out, line, length);
- return;
- }
-
- if (!(line_colors = malloc(length))
- || !(raster_line = malloc(raster_bytes * planes)))
- fatal_err((catgets(nlmsg_fd,NL_SETN,17,
- "Could not allocate raster line memory.")));
-
- if (device == PJET || Direct_or_TrueColor)
- download_colors(line, length, device);
-
- /* Map the line's colors into output color index numbers */
- if (Direct_or_TrueColor)
- for (n=0, lc=line_colors, lp=line; n<length; n++)
- *lc++ = (char) lookup_color_index(*lp++);
- else
- for (n=0, lc=line_colors, lp=line; n<length; n++)
- *lc++ = (char) colormap[*lp++];
-
- for (p=0; p<planes; p++) {
- bytebits = 0;
- n = length;
- lc = line_colors;
- rl = &raster_line[raster_bytes * p];
- while (n-- > 0) {
- bit = (*lc++ >> p) & 0x01;
- e = scale;
- while (e--) {
- byte = (byte << 1) | bit;
- bytebits++;
- if (bytebits == 8) {
- *rl++ = byte;
- bytebits = 0;
- }
- }
- }
- if (bytebits)
- *rl = byte << (8 - bytebits);
- }
-
- e = scale;
- while (e--) {
- for (p=0; p<planes; p++) {
- fprintf(out,"\033*b%d%c", raster_bytes, (p+1 == planes) ? 'W' : 'V');
- fwrite(&raster_line[raster_bytes * p], 1, raster_bytes, out);
- }
- }
-
- free(line_colors);
- free(raster_line);
- }
-
-
- void write_portrait_Z_image (out, scale, device)
- FILE *out;
- int scale;
- enum device device;
- {
- int x, y;
- int width = limit.width;
- int height = limit.height;
- long *line, *lp;
-
- if (!(line = (long *) malloc(width * sizeof(long))))
- fatal_err((catgets(nlmsg_fd,NL_SETN,18,
- "Could not allocate memory for image line buffer.")));
-
- for (y=0; y<height; y++) {
-
- for (x=0, lp=line; x<width; x++)
- *lp++ = Z_image_pixel(x,y);
-
- write_raster_line(out, scale, device, line, width);
- }
- }
-
-
-
- void write_landscape_Z_image (out, scale, device)
- FILE *out;
- int scale;
- enum device device;
- {
- int x, y;
- int width = limit.height;
- int height = limit.width;
- long *line, *lp;
-
- if (!(line = (long *) malloc(width * sizeof(long))))
- fatal_err((catgets(nlmsg_fd,NL_SETN,19,
- "Could not allocate memory for image line buffer.")));
-
- for (x=0; x<height; x++) {
-
- for (y=width-1, lp=line; y>=0; y--)
- *lp++ = Z_image_pixel(x,y);
-
- write_raster_line(out, scale, device, line, width);
- }
- }
-
-
- void write_portrait_XY_image (out, scale, device)
- FILE *out;
- int scale;
- enum device device;
- {
- int x, y;
- int width = limit.width;
- int height = limit.height;
- long *line, *lp;
-
- if (!(line = (long *) malloc(width * sizeof(long))))
- fatal_err((catgets(nlmsg_fd,NL_SETN,20,
- "Could not allocate memory for image line buffer.")));
-
- for (y=0; y<height; y++) {
-
- for (x=0, lp=line; x<width; x++)
- *lp++ = XY_image_pixel(x,y);
-
- write_raster_line(out, scale, device, line, width);
- }
- }
-
-
-
- void write_landscape_XY_image (out, scale, device)
- FILE *out;
- int scale;
- enum device device;
- {
- int x, y;
- int width = limit.height;
- int height = limit.width;
- long *line, *lp;
-
- if (!(line = (long *) malloc(width * sizeof(long))))
- fatal_err((catgets(nlmsg_fd,NL_SETN,21,
- "Could not allocate memory for image line buffer.")));
-
- for (x=0; x<height; x++) {
-
- for (y=width-1, lp=line; y>=0; y--)
- *lp++ = XY_image_pixel(x,y);
-
- write_raster_line(out, scale, device, line, width);
- }
- }
-
-
- void write_Z_image (out, scale, orient, device)
- FILE *out;
- int scale;
- enum orientation orient;
- enum device device;
- {
- if (orient == PORTRAIT) {
- write_portrait_Z_image(out, scale, device);
- } else
- write_landscape_Z_image(out, scale, device);
- }
-
-
-
- void write_XY_image (out, scale, orient, device)
- FILE *out;
- int scale;
- enum orientation orient;
- enum device device;
- {
- if (xwd_header.pixmap_depth > 1)
- fatal_err((catgets(nlmsg_fd,NL_SETN,22,
- "XY format image, multiplane images must be Z format.")));
-
- if (orient == PORTRAIT) {
- write_portrait_XY_image(out, scale, device);
- } else
- write_landscape_XY_image(out, scale, device);
- }
-
-
-
- void write_image (out, scale, orient, device)
- FILE *out;
- int scale;
- enum orientation orient;
- enum device device;
- {
- switch (xwd_header.pixmap_format) {
- case XYPixmap:
- write_XY_image(out, scale, orient, device); break;
- case ZPixmap:
- write_Z_image(out, scale, orient, device); break;
- default:
- fatal_err((catgets(nlmsg_fd,NL_SETN,23, "image not in XY or Z format.")));
- }
- }
-
-
- void x2jet(in, out, scale, density, width, height, left, top,
- header, trailer, orient, invert,
- initial_formfeed, position_on_page, slide,
- device, cutoff, gamma, render)
- FILE *in, *out;
- int scale, density;
- int width, height, left, top; /* in 300ths of an inch */
- char *header, *trailer;
- enum orientation orient;
- int invert, initial_formfeed, position_on_page, slide;
- enum device device;
- unsigned int cutoff;
- float gamma;
- int render;
- {
- int paintjet = FALSE;
-
- true_scale = scale;
-
- if (device != LJET)
- paintjet = TRUE;
-
- read_xwd_data(in);
-
- Z_pixel_mask = ~(0xFFFFFFFFL << xwd_header.pixmap_depth);
-
- prepare_color_mapping(invert, paintjet, cutoff, out);
-
- scale_and_orient_image(&scale, &density, width, height, left, top,
- header, trailer,
- &orient, position_on_page, device);
-
- write_image_prefix(out, scale, density, header, device, position_on_page,
- initial_formfeed, orient, gamma, render, slide);
-
- write_image(out, scale, orient, device);
-
- write_image_suffix(out, trailer, position_on_page, slide, render, device);
-
- fclose(out);
- }
-
-
- void fatal_err (s)
- char * s;
- {
- fprintf(stderr, "%s: %s\n", progname, s);
- exit(1);
- }
-
- void fatal_err2 (s, a1, a2, a3)
- char *s;
- char *a1, *a2, *a3;
- {
- fprintf(stderr, "%s: ", progname);
- fprintf(stderr, s, a1, a2, a3);
- exit(1);
- }
-