home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1992, 2000 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
-
- /*$Id: gdevpcl.c,v 1.4 2000/09/19 19:00:16 lpd Exp $ */
- /* Utilities for PCL printers */
- #include "gdevprn.h"
- #include "gdevpcl.h"
-
- /* ------ Get paper size ------ */
-
- /* Get the paper size code, based on width and height. */
- int
- gdev_pcl_paper_size(gx_device * dev)
- {
- float height_inches = dev->height / dev->y_pixels_per_inch;
-
- return
- (height_inches >= 33.2 ? PAPER_SIZE_A0 :
- height_inches >= 23.5 ? PAPER_SIZE_A1 :
- height_inches >= 17.1 ? PAPER_SIZE_A2 :
- height_inches >= 16.6 ? PAPER_SIZE_LEDGER : /* see gdevpcl.h */
- height_inches >= 14.1 ? PAPER_SIZE_A3 :
- height_inches >= 11.8 ? PAPER_SIZE_LEGAL :
- height_inches >= 11.1 ? PAPER_SIZE_A4 :
- PAPER_SIZE_LETTER);
- }
-
- /* ------ Color mapping ------ */
-
- /* The PaintJet and DeskJet 500C use additive colors in separate planes. */
- /* We only keep one bit of color, with 1 = R, 2 = G, 4 = B. */
- /* Because the buffering routines assume 0 = white, */
- /* we complement all the color components. */
- #define cv_shift (sizeof(gx_color_value) * 8 - 1)
-
- /* Map an RGB color to a printer color. */
- gx_color_index
- gdev_pcl_3bit_map_rgb_color(gx_device * dev,
- gx_color_value r, gx_color_value g, gx_color_value b)
- {
- return (((b >> cv_shift) << 2) + ((g >> cv_shift) << 1) + (r >> cv_shift)) ^ 7;
- }
-
- /* Map the printer color back to RGB. */
- int
- gdev_pcl_3bit_map_color_rgb(gx_device * dev, gx_color_index color,
- gx_color_value prgb[3])
- {
- ushort cc = (ushort) color ^ 7;
-
- prgb[0] = -(cc & 1);
- prgb[1] = -((cc >> 1) & 1);
- prgb[2] = -(cc >> 2);
- return 0;
- }
-
- /* ------ Compression ------ */
-
- /*
- * Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp.
- * Compresses data from row up to end_row, storing the result
- * starting at compressed. Returns the number of bytes stored.
- * Runs of K<=127 literal bytes are encoded as K-1 followed by
- * the bytes; runs of 2<=K<=127 identical bytes are encoded as
- * 257-K followed by the byte.
- * In the worst case, the result is N+(N/127)+1 bytes long,
- * where N is the original byte count (end_row - row).
- * To speed up the search, we examine an entire word at a time.
- * We will miss a few blocks of identical bytes; tant pis.
- */
- int
- gdev_pcl_mode2compress_padded(const word * row, const word * end_row,
- byte * compressed, bool pad)
- {
- register const word *exam = row; /* word being examined in the row to compress */
- register byte *cptr = compressed; /* output pointer into compressed bytes */
-
- while (exam < end_row) { /* Search ahead in the input looking for a run */
- /* of at least 4 identical bytes. */
- const byte *compr = (const byte *)exam;
- const byte *end_dis;
- const word *next;
- register word test = *exam;
-
- while (((test << 8) ^ test) > 0xff) {
- if (++exam >= end_row)
- break;
- test = *exam;
- }
-
- /* Find out how long the run is */
- end_dis = (const byte *)exam;
- if (exam == end_row) { /* no run */
- /* See if any of the last 3 "dissimilar" bytes are 0. */
- if (!pad && end_dis > compr && end_dis[-1] == 0) {
- if (end_dis[-2] != 0)
- end_dis--;
- else if (end_dis[-3] != 0)
- end_dis -= 2;
- else
- end_dis -= 3;
- }
- next = --end_row;
- } else {
- next = exam + 1;
- while (next < end_row && *next == test)
- next++;
- /* See if any of the last 3 "dissimilar" bytes */
- /* are the same as the repeated byte. */
- if (end_dis > compr && end_dis[-1] == (byte) test) {
- if (end_dis[-2] != (byte) test)
- end_dis--;
- else if (end_dis[-3] != (byte) test)
- end_dis -= 2;
- else
- end_dis -= 3;
- }
- }
-
- /* Now [compr..end_dis) should be encoded as dissimilar, */
- /* and [end_dis..next) should be encoded as similar. */
- /* Note that either of these ranges may be empty. */
-
- for (;;) { /* Encode up to 127 dissimilar bytes */
- uint count = end_dis - compr; /* uint for faster switch */
-
- switch (count) { /* Use memcpy only if it's worthwhile. */
- case 6:
- cptr[6] = compr[5];
- case 5:
- cptr[5] = compr[4];
- case 4:
- cptr[4] = compr[3];
- case 3:
- cptr[3] = compr[2];
- case 2:
- cptr[2] = compr[1];
- case 1:
- cptr[1] = compr[0];
- *cptr = count - 1;
- cptr += count + 1;
- case 0: /* all done */
- break;
- default:
- if (count > 127)
- count = 127;
- *cptr++ = count - 1;
- memcpy(cptr, compr, count);
- cptr += count, compr += count;
- continue;
- }
- break;
- }
-
- { /* Encode up to 127 similar bytes. */
- /* Note that count may be <0 at end of row. */
- int count = (const byte *)next - end_dis;
-
- while (count > 0) {
- int this = (count > 127 ? 127 : count);
-
- *cptr++ = 257 - this;
- *cptr++ = (byte) test;
- count -= this;
- }
- exam = next;
- }
- }
- return (cptr - compressed);
- }
- int
- gdev_pcl_mode2compress(const word * row, const word * end_row,
- byte * compressed)
- {
- return gdev_pcl_mode2compress_padded(row, end_row, compressed, false);
- }
-
- /*
- * Mode 3 compression routine for the HP LaserJet III family.
- * Compresses bytecount bytes starting at current, storing the result
- * in compressed, comparing against and updating previous.
- * Returns the number of bytes stored. In the worst case,
- * the number of bytes is bytecount+(bytecount/8)+1.
- */
- int
- gdev_pcl_mode3compress(int bytecount, const byte * current, byte * previous, byte * compressed)
- {
- register const byte *cur = current;
- register byte *prev = previous;
- register byte *out = compressed;
- const byte *end = current + bytecount;
-
- while (cur < end) { /* Detect a maximum run of unchanged bytes. */
- const byte *run = cur;
- register const byte *diff;
- const byte *stop;
- int offset, cbyte;
-
- while (cur < end && *cur == *prev) {
- cur++, prev++;
- }
- if (cur == end)
- break; /* rest of row is unchanged */
- /* Detect a run of up to 8 changed bytes. */
- /* We know that *cur != *prev. */
- diff = cur;
- stop = (end - cur > 8 ? cur + 8 : end);
- do {
- *prev++ = *cur++;
- }
- while (cur < stop && *cur != *prev);
- /* Now [run..diff) are unchanged, and */
- /* [diff..cur) are changed. */
- /* Generate the command byte(s). */
- offset = diff - run;
- cbyte = (cur - diff - 1) << 5;
- if (offset < 31)
- *out++ = cbyte + offset;
- else {
- *out++ = cbyte + 31;
- offset -= 31;
- while (offset >= 255)
- *out++ = 255, offset -= 255;
- *out++ = offset;
- }
- /* Copy the changed data. */
- while (diff < cur)
- *out++ = *diff++;
- }
- return out - compressed;
- }
-
- /*
- * Mode 9 2D compression for the HP DeskJets . This mode can give
- * very good compression ratios, especially if there are areas of flat
- * colour (or blank areas), and so is 'highly recommended' for colour
- * printing in particular because of the very large amounts of data which
- * can be generated
- */
- int
- gdev_pcl_mode9compress(int bytecount, const byte *current,
- const byte *previous, byte *compressed)
- {
- register const byte *cur = current;
- register const byte *prev = previous;
- register byte *out = compressed;
- const byte *end = current + bytecount;
-
- while (cur < end) { /* Detect a run of unchanged bytes. */
- const byte *run = cur;
- register const byte *diff;
- int offset;
-
- while (cur < end && *cur == *prev) {
- cur++, prev++;
- }
- if (cur == end)
- break; /* rest of row is unchanged */
- /* Detect a run of changed bytes. */
- /* We know that *cur != *prev. */
- diff = cur;
- do {
- prev++;
- cur++;
- }
- while (cur < end && *cur != *prev);
- /* Now [run..diff) are unchanged, and */
- /* [diff..cur) are changed. */
- offset = diff - run;
- {
- const byte *stop_test = cur - 4;
- int dissimilar, similar;
-
- while (diff < cur) {
- const byte *compr = diff;
- const byte *next; /* end of run */
- byte value = 0;
-
- while (diff <= stop_test &&
- ((value = *diff) != diff[1] ||
- value != diff[2] ||
- value != diff[3]))
- diff++;
-
- /* Find out how long the run is */
- if (diff > stop_test) /* no run */
- next = diff = cur;
- else {
- next = diff + 4;
- while (next < cur && *next == value)
- next++;
- }
-
- #define MAXOFFSETU 15
- #define MAXCOUNTU 7
- /* output 'dissimilar' bytes, uncompressed */
- if ((dissimilar = diff - compr)) {
- int temp, i;
-
- if ((temp = --dissimilar) > MAXCOUNTU)
- temp = MAXCOUNTU;
- if (offset < MAXOFFSETU)
- *out++ = (offset << 3) | (byte) temp;
- else {
- *out++ = (MAXOFFSETU << 3) | (byte) temp;
- offset -= MAXOFFSETU;
- while (offset >= 255) {
- *out++ = 255;
- offset -= 255;
- }
- *out++ = offset;
- }
- if (temp == MAXCOUNTU) {
- temp = dissimilar - MAXCOUNTU;
- while (temp >= 255) {
- *out++ = 255;
- temp -= 255;
- }
- *out++ = (byte) temp;
- }
- for (i = 0; i <= dissimilar; i++)
- *out++ = *compr++;
- offset = 0;
- } /* end uncompressed */
- #undef MAXOFFSETU
- #undef MAXCOUNTU
-
- #define MAXOFFSETC 3
- #define MAXCOUNTC 31
- /* output 'similar' bytes, run-length encoded */
- if ((similar = next - diff)) {
- int temp;
-
- if ((temp = (similar -= 2)) > MAXCOUNTC)
- temp = MAXCOUNTC;
- if (offset < MAXOFFSETC)
- *out++ = 0x80 | (offset << 5) | (byte) temp;
- else {
- *out++ = 0x80 | (MAXOFFSETC << 5) | (byte) temp;
- offset -= MAXOFFSETC;
- while (offset >= 255) {
- *out++ = 255;
- offset -= 255;
- }
- *out++ = offset;
- }
- if (temp == MAXCOUNTC) {
- temp = similar - MAXCOUNTC;
- while (temp >= 255) {
- *out++ = 255;
- temp -= 255;
- }
- *out++ = (byte) temp;
- }
- *out++ = value;
- offset = 0;
- } /* end compressed */
- #undef MAXOFFSETC
- #undef MAXCOUNTC
-
- diff = next;
- }
- }
- }
- return out - compressed;
- }
-