diff options
Diffstat (limited to 'gs/contrib/pcl3/eprn/eprnrend.c.orig')
-rw-r--r-- | gs/contrib/pcl3/eprn/eprnrend.c.orig | 1141 |
1 files changed, 0 insertions, 1141 deletions
diff --git a/gs/contrib/pcl3/eprn/eprnrend.c.orig b/gs/contrib/pcl3/eprn/eprnrend.c.orig deleted file mode 100644 index cf453c966..000000000 --- a/gs/contrib/pcl3/eprn/eprnrend.c.orig +++ /dev/null @@ -1,1141 +0,0 @@ -/****************************************************************************** - File: $Id: eprnrend.c,v 1.15 2001/08/01 05:12:56 Martin Rel $ - Contents: Colour rendering functionality for the ghostscript device 'eprn' - Author: Martin Lottermoser, Greifswaldstrasse 28, 38124 Braunschweig, - Germany. E-mail: Martin.Lottermoser@t-online.de. - -******************************************************************************* -* * -* Copyright (C) 2000, 2001 by Martin Lottermoser * -* All rights reserved * -* * -******************************************************************************* - - Preprocessor variables: - - EPRN_TRACE - Define this to enable tracing. Only useful for development. - - EPRN_TRAILING_BIT_BUG_FIXED - Define this to deactivate compensation for a bug in ghostscript which - leads to the last pixel in an RGB line being black instead of white. - This occurs at least in gs 6.01 and 6.50. The correction covers only - the one-bit-per-colorant case and is equivalent to clipping the pixel. - -******************************************************************************* - - The eprn device uses 'gx_color_index' values with varying interpretations, - depending on the colour model and the rendering method, and stores them at - different pixmaps depths, normally using the smallest depth which can - accommodate all colorants at the same number of bits per colorant. - - To simplify matters, a field for the black component is always included, even - for RGB and CMY, i.e., there are either 1 or 4 bit fields in a - 'gx_color_index' value. If there are 4, the interpretation is either YMCK or - BGRK, looking from left to right (most to least significant). The width of - the fields can be found in the 'bits_per_colorant' variable in the eprn part - of the device instance. - - Within each colorant field, not all bits need be used. Except when using the - *_max() colour mapping functions, the values returned by - eprn_bits_for_levels() for the parameters 'black_levels' and - 'non_black_levels' determine the number of bits which are actually - meaningful. Only the last (least significant) bits are used. - -******************************************************************************/ - -/* Configuration management identification */ -#ifndef lint -static const char - cm_id[] = "@(#)$Id: eprnrend.c,v 1.15 2001/08/01 05:12:56 Martin Rel $"; -#endif - -/*****************************************************************************/ - -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 500 -#endif - -/* Special Aladdin header, must be included before <sys/types.h> on some - platforms (e.g., FreeBSD). */ -#include "std.h" - -/* Standard headers */ -#include <assert.h> -#include <stdlib.h> - -/* Ghostscript headers */ -#ifdef EPRN_TRACE -#include "gdebug.h" -#endif /* EPRN_TRACE */ - -/* Special headers */ -#include "gdeveprn.h" - -/*****************************************************************************/ - -/* Macros for 'gx_color_index' values used mainly for non-monochrome modes and - a pixmap depth of 4 */ - -/* Colorants bits, numbered from 0 on the right to 3 on the left */ -#define COLORANT_0_BIT 1U -#define COLORANT_1_BIT 2U -#define COLORANT_2_BIT 4U -#define COLORANT_3_BIT 8U - -/* Alias names for the bits in particular colour models */ -#define BLACK_BIT COLORANT_0_BIT -#define CYAN_BIT COLORANT_1_BIT -#define MAGENTA_BIT COLORANT_2_BIT -#define YELLOW_BIT COLORANT_3_BIT -#define RED_BIT COLORANT_1_BIT -#define GREEN_BIT COLORANT_2_BIT -#define BLUE_BIT COLORANT_3_BIT - -/* Bit plane indices for splitting */ -#define COLORANT_0_INDEX 0 -#define COLORANT_1_INDEX 1 -#define COLORANT_2_INDEX 2 -#define COLORANT_3_INDEX 3 - -/* Macro to extract the dominant 8 bits from a 'gx_color_value'. This - definition assumes that 'gx_color_value' uses the least significant 16 bits - of the underlying type (unsigned short). Splitting this part off looks - inefficient because left shifts will usually follow, but I'm relying on the - compiler to be sufficiently intelligent to eliminate this inefficiency. - This way the code is easier to check. - The type cast is needed to prevent problems with negative values on - platforms where 'gx_color_index' has more bits than 'int'. - */ -#define dominant_8bits(value) ((unsigned int)((value) >> 8)) - -/****************************************************************************** - - Function: eprn_number_of_bitplanes - - Total number of bit planes returned by eprn_get_planes(). - This value is constant while the device is open. - -******************************************************************************/ - -unsigned int eprn_number_of_bitplanes(eprn_Device *dev) -{ - return dev->eprn.output_planes; -} - -/****************************************************************************** - - Function: eprn_number_of_octets - - Maximal lengths, in terms of the number of 'eprn_Octet' instances, for each - bit plane returned by eprn_get_planes() for this device. These values - are constant while the device is open. - -******************************************************************************/ - -void eprn_number_of_octets(eprn_Device *dev, unsigned int lenghts[]) -{ - unsigned int j, length; - - length = (dev->eprn.octets_per_line + dev->color_info.depth - 1)/ - dev->color_info.depth; - /* This results in length >= ceiling((number of pixels per line)/8) - because: - 8 * octets_per_line >= pixels_per_line * depth - <==> octets_per_line/depth >= pixels_per_line/8 - where division is to be understood as exact. - */ - - for (j = 0; j < dev->eprn.output_planes; j++) lenghts[j] = length; - - return; -} - -/****************************************************************************** - - Function: eprn_map_rgb_color_for_RGB - - Colour mapping function for the process colour model 'DeviceRGB' and - 2 intensity levels per colorant. - -******************************************************************************/ - -gx_color_index eprn_map_rgb_color_for_RGB(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value red = cv[0], green = cv[1], blue = cv[2]; - static const gx_color_value half = gx_max_color_value/2; - gx_color_index value = 0; - const eprn_Device *dev = (eprn_Device *)device; - -#ifdef EPRN_TRACE - if_debug3(EPRN_TRACE_CHAR, - "! eprn_map_rgb_color_for_RGB() called for RGB = (%hu, %hu, %hu),\n", - red, green, blue); -#endif - - assert(dev->eprn.colour_model == eprn_DeviceRGB); - - if (red > half) value |= RED_BIT; - if (green > half) value |= GREEN_BIT; - if (blue > half) value |= BLUE_BIT; - -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value); -#endif - return value; -} - -/****************************************************************************** - - Function: eprn_map_rgb_color_for_CMY_or_K - - Colour mapping function for the native colour spaces DeviceGray and DeviceRGB - and a process colour model using a selection of CMYK colorants with at most - 2 intensity levels per colorant. This function must not be called for the - process colour models 'DeviceRGB' and 'DeviceCMYK'. - -******************************************************************************/ - -gx_color_index eprn_map_rgb_color_for_CMY_or_K(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value red = cv[0], green = cv[1], blue = cv[2]; - static const gx_color_value half = gx_max_color_value/2; - gx_color_index value = (CYAN_BIT | MAGENTA_BIT | YELLOW_BIT); - const eprn_Device *dev = (eprn_Device *)device; - -#ifdef EPRN_TRACE - if_debug3(EPRN_TRACE_CHAR, - "! eprn_map_rgb_color_for_CMY_or_K() called for RGB = (%hu, %hu, %hu),\n", - red, green, blue); -#endif - - assert(dev->eprn.colour_model == eprn_DeviceGray && red == green && - green == blue && (blue == 0 || blue == gx_max_color_value) || - dev->eprn.colour_model == eprn_DeviceCMY || - dev->eprn.colour_model == eprn_DeviceCMY_plus_K); - - /* Map to CMY */ - if (red > half) value &= ~CYAN_BIT; - if (green > half) value &= ~MAGENTA_BIT; - if (blue > half) value &= ~YELLOW_BIT; - - /* Remap composite black to true black if available */ - if (dev->eprn.colour_model != eprn_DeviceCMY && - value == (CYAN_BIT | MAGENTA_BIT | YELLOW_BIT)) - value = BLACK_BIT; - -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value); -#endif - return value; -} - -/****************************************************************************** - - Function: eprn_map_rgb_color_for_RGB_flex - - This is a 'map_rgb_color' method for the process colour model 'DeviceRGB' - supporting any number of intensity levels. - -******************************************************************************/ - -gx_color_index eprn_map_rgb_color_for_RGB_flex(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value red = cv[0], green = cv[1], blue = cv[2]; - gx_color_index value = 0; - gx_color_value step; - unsigned int level; - const eprn_Eprn *eprn = &((eprn_Device *)device)->eprn; - -#ifdef EPRN_TRACE - if_debug3(EPRN_TRACE_CHAR, - "! eprn_map_rgb_color_for_RGB_flex() called for RGB = (%hu, %hu, %hu),\n", - red, green, blue); -#endif - - /* See the discussion in eprn_map_cmyk_color_flex() below. */ - - step = gx_max_color_value/eprn->non_black_levels; - - /* The order has to be BGR from left to right */ - level = blue/step; - if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; - value = level << eprn->bits_per_colorant; - level = green/step; - if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; - value = (value | level) << eprn->bits_per_colorant; - level = red/step; - if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; - value = (value | level) << eprn->bits_per_colorant; - -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value); -#endif - return value; -} - -/****************************************************************************** - - Function: eprn_map_rgb_color_for_CMY_or_K_flex - - This is a flexible 'map_rgb_color' method. It must not be called for the - process colour models 'DeviceRGB' and 'DeviceCMYK'. - -******************************************************************************/ - -gx_color_index eprn_map_rgb_color_for_CMY_or_K_flex(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value red = cv[0], green = cv[1], blue = cv[2]; - const eprn_Device *dev = (eprn_Device *)device; - -#ifdef EPRN_TRACE - if_debug3(EPRN_TRACE_CHAR, - "! eprn_map_rgb_color_for_CMY_or_K_flex() called for " - "RGB = (%hu, %hu, %hu).\n", - red, green, blue); -#endif - - /* Treat pure grey levels differently if we have black. This implies that for - CMY+K only "true" grey shades will be printed with black ink, all others - will be mixed from CMY. */ - gx_color_value tmpcv[4]; - if (dev->eprn.colour_model != eprn_DeviceCMY && red == green && green == blue) { - tmpcv[0] = 0; tmpcv[1] = 0; tmpcv[2] = 0; - tmpcv[3] = gx_max_color_value - red; - return eprn_map_cmyk_color_flex(device, tmpcv); - - } - tmpcv[0] = gx_max_color_value - red; - tmpcv[1] = gx_max_color_value - green; - tmpcv[2] = gx_max_color_value - blue; - tmpcv[3] = 0; - return eprn_map_cmyk_color_flex(device, tmpcv); -} - -/****************************************************************************** - - Function: eprn_map_rgb_color_for_RGB_max - - Colour mapping function for the process colour model 'DeviceRGB' retaining as - much information as possible. - -******************************************************************************/ - -gx_color_index eprn_map_rgb_color_for_RGB_max(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value red = cv[0], green = cv[1], blue = cv[2]; - gx_color_index value; - -#ifdef EPRN_TRACE - if_debug3(EPRN_TRACE_CHAR, - "! eprn_map_rgb_color_for_RGB_max() called for RGB = (%hu, %hu, %hu),\n", - red, green, blue); -#endif - - value = dominant_8bits(red) << 8; - value |= dominant_8bits(green) << 16; - value |= dominant_8bits(blue) << 24; - -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, " returning 0x%08lX.\n", (unsigned long)value); -#endif - return value; -} - -/****************************************************************************** - - Function: eprn_map_rgb_color_for_CMY_or_K_max - - "Maximal" colour mapping function for the process colour models "DeviceGray", - "DeviceCMY", and "CMY+K". - -******************************************************************************/ - -gx_color_index eprn_map_rgb_color_for_CMY_or_K_max(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value red = cv[0], green = cv[1], blue = cv[2]; - const eprn_Device *dev = (eprn_Device *)device; - -#ifdef EPRN_TRACE - if_debug3(EPRN_TRACE_CHAR, - "! eprn_map_rgb_color_for_CMY_or_K_max() called for " - "RGB = (%hu, %hu, %hu).\n", - red, green, blue); -#endif - - gx_color_value tmpcv[4]; - if (dev->eprn.colour_model == eprn_DeviceGray) { - tmpcv[0] = 0; tmpcv[1] = 0; tmpcv[2] = 0; - tmpcv[3] = gx_max_color_value - red; - return eprn_map_cmyk_color_max(device, tmpcv); - } - /* Note that the conversion from composite black to true black for CMY+K can - only happen at the output pixel level, not here. */ - tmpcv[0] = gx_max_color_value - red; - tmpcv[1] = gx_max_color_value - green; - tmpcv[2] = gx_max_color_value - blue; - tmpcv[3] = 0; - return eprn_map_cmyk_color_max(device, tmpcv); -} - -/****************************************************************************** - - Function: eprn_map_color_rgb - - This function is a 'map_color_rgb' method. - - Such a method should return an RGB triple for the specified 'color'. This is - apparently intended for devices supporting colour maps. - - The function param_HWColorMap() in gsdparam.c tries to compile such a - colour map by calling this method repeatedly for all values from 0 to - 2^color_info.depth - 1, provided the depth is less than or equal to 8 and - the process colour model is not DeviceCMYK. If the function for one of these - values returns a negative code, the assumption seems to be that there is no - such colour map. Because there is a default method which always returns zero, - such a colour map is always constructed if a device does not implement its - own 'map_color_rgb' method. This can be seen in the appearance of the - "HWColorMap" page device parameter. - - The key purpose of this function is therefore to return a negative code. - -******************************************************************************/ - -int eprn_map_color_rgb(gx_device *device, gx_color_index color, - gx_color_value rgb[]) -{ -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, - "! eprn_map_color_rgb() called for 0x%lX.\n", (unsigned long)color); -#endif - - /* Just to be safe we return defined values (white) */ - if (((eprn_Device *)device)->eprn.colour_model == eprn_DeviceRGB) - rgb[0] = rgb[1] = rgb[2] = gx_max_color_value; - else - rgb[0] = rgb[1] = rgb[2] = 0; - - return -1; -} - -/****************************************************************************** - - Function: eprn_map_cmyk_color - - Colour mapping function for a process colour model of 'DeviceCMYK' with - 2 intensity levels for all colorants. - -******************************************************************************/ - -gx_color_index eprn_map_cmyk_color(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value cyan = cv[0], magenta = cv[1], yellow = cv[2], black = cv[3]; - gx_color_index value = 0; - static const gx_color_value threshold = gx_max_color_value/2; - -#ifdef EPRN_TRACE - if_debug4(EPRN_TRACE_CHAR, - "! eprn_map_cmyk_color() called for CMYK = (%hu, %hu, %hu, %hu),\n", - cyan, magenta, yellow, black); -#endif - - if (cyan > threshold) value |= CYAN_BIT; - if (magenta > threshold) value |= MAGENTA_BIT; - if (yellow > threshold) value |= YELLOW_BIT; - if (black > threshold) value |= BLACK_BIT; - -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value); -#endif - return value; -} - -/****************************************************************************** - - Function: eprn_map_cmyk_color_flex - - This is a 'map_cmyk_color' method supporting arbitrary numbers of intensity - levels. It may be called for every colour model except DeviceRGB. Colorants - not present in the model will be ignored. - -******************************************************************************/ - -gx_color_index eprn_map_cmyk_color_flex(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value cyan = cv[0], magenta = cv[1], yellow = cv[2], black = cv[3]; - gx_color_index value = 0; - gx_color_value step; - unsigned int level; - const eprn_Eprn *eprn = &((eprn_Device *)device)->eprn; - -#ifdef EPRN_TRACE - if_debug4(EPRN_TRACE_CHAR, - "! eprn_map_cmyk_color_flex() called for CMYK = (%hu, %hu, %hu, %hu),\n", - cyan, magenta, yellow, black); -#endif - - /* I can think of three linear methods to extract discrete values from a - continuous intensity in the range [0, 1]: - (a) multiply by the number of levels minus 1 and truncate, - (b) multiply by the number of levels minus 1 and round, and - (c) multiply by the number of levels and truncate, except for an - intensity of 1 in which case one returns the number of levels minus 1. - For intensity values which can be represented exactly, i.e., - - intensity = i/(levels-1) for some non-negative i < levels, - - these three methods are identical. (a) is however inappropriate here - because for less than 32 levels ghostscript already provides intensity - values which have been adjusted to a representable level. A rounding - error could now result in a level which is too small by one. I prefer (c) - because it gives equal shares to all levels. - - I'm using integer arithmetic here although floating point numbers would - be more accurate. This routine may, however, be called quite frequently, - and the loss in accuray is acceptable as long as the values determined - for 'step' are large compared to the number of levels. If you consider - "large" as meaning "10 times as large", the critical boundary is at about - 81 levels. The highest number of intensity levels at present supported by - HP DeskJets is apparently 4. - - A more accurate implementation would determine 'step' as a floating point - value, divide the intensity by it, and take the floor (entier) of the - result as the component intensity. - */ - - /* The order has to be (YMC)(K) from left to right */ - if (eprn->colour_model != eprn_DeviceGray) { - step = gx_max_color_value/eprn->non_black_levels; - - level = yellow/step; - if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; - value = level << eprn->bits_per_colorant; - level = magenta/step; - if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; - value = (value | level) << eprn->bits_per_colorant; - level = cyan/step; - if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1; - value = (value | level) << eprn->bits_per_colorant; - } - if (eprn->colour_model != eprn_DeviceCMY) { - step = gx_max_color_value/eprn->black_levels; - level = black/step; - if (level >= eprn->black_levels) level = eprn->black_levels - 1; - value |= level; - } - -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, " returning 0x%lX.\n", (unsigned long)value); -#endif - return value; -} - -/****************************************************************************** - - Function: eprn_map_cmyk_color_max - - This is a 'map_cmyk_color' method retaining as much colour information as - possible. The reduction to the printer's capabilities must happen in the - output routine. - -******************************************************************************/ - -gx_color_index eprn_map_cmyk_color_max(gx_device *device, - const gx_color_value cv[]) -{ - gx_color_value cyan = cv[0], magenta = cv[1], yellow = cv[2], black = cv[3]; - gx_color_index value; - -#ifdef EPRN_TRACE - if_debug4(EPRN_TRACE_CHAR, - "! eprn_map_cmyk_color_max() called for CMYK = (%hu, %hu, %hu, %hu),\n", - cyan, magenta, yellow, black); -#endif - - value = dominant_8bits(black); - value |= dominant_8bits(cyan) << 8; - value |= dominant_8bits(magenta) << 16; - value |= dominant_8bits(yellow) << 24; - -#ifdef EPRN_TRACE - if_debug1(EPRN_TRACE_CHAR, " returning 0x%08lX.\n", (unsigned long)value); -#endif - return value; -} - -/****************************************************************************** - - Function: eprn_finalize - - This function fills the last octet in a set of bit planes with white if - needed and sets the lengths of all these planes. - - 'is_RGB' denotes whether the colour model is eprn_DeviceRGB, - 'non_black_levels' is the number of intensity levels for non-black colorants, - 'planes' the number of bit planes, - 'plane' points to an array of at least 'planes' bit planes, - 'ptr' points to an array of at least 'planes' pointers into the bit planes, - 'pixels' is the number of pixels written to the group of bit planes. - - If 'pixels' is divisible by 8, the 'ptr' pointers point to octets after - the last completely written octets. Otherwise, they point to the last - incompletely written octet in which the pixels written so far occupy the - least significant bits. - -******************************************************************************/ - -void eprn_finalize(bool is_RGB, unsigned int non_black_levels, - int planes, eprn_OctetString *plane, eprn_Octet **ptr, int pixels) -{ - int j; - - /* Execute remaining left shifts in the last octet of the output planes when - the number of pixels is not a multiple of 8, and fill with white on the - right */ - if (pixels % 8 != 0) { - int shift = 8 - pixels % 8; - - if (is_RGB) { - /* White may be any intensity, but it's the same for all three colorants, - and it's the highest. */ - eprn_Octet imax = non_black_levels - 1; - int c, rgb_planes = eprn_bits_for_levels(non_black_levels); - - j = 0; /* next output plane */ - - /* Loop over RGB */ - for (c = 0; c < 3; c++) { - eprn_Octet value = imax; - int m; - - /* Loop over all planes for this colorant */ - for (m = 0; m < rgb_planes; m++, j++) { - eprn_Octet bit = value & 1; - int p; - - value = value >> 1; - - /* Put the bit into all remaining pixels for this plane */ - for (p = 0; p < shift; p++) - *ptr[j] = (*ptr[j] << 1) | bit; - } - } - } - else /* White is zero */ - for (j = 0; j < planes; j++) - *ptr[j] = *ptr[j] << shift; - - /* Advance all plane pointers by 1 */ - for (j = 0; j < planes; j++) ptr[j]++; - } - - /* Set the lengths of the bit plane strings */ - for (j = 0; j < planes; j++) { - if (pixels == 0) plane[j].length = 0; - else plane[j].length = ptr[j] - plane[j].str; - } - - return; -} - -/****************************************************************************** - - Function: split_line_le8 - - This is the first of the "split_line implementations". See the body of - eprn_get_planes() for the calling conventions common to them. - - This particular implementation has the following restrictions: - - The pixmap depth must be a divisor of 8. - -******************************************************************************/ - -static void split_line_le8(eprn_Device *dev, const eprn_Octet *line, - int length, eprn_OctetString plane[]) -{ - gx_color_index - pixel; - int - black_planes, /* number of planes to send for black */ - non_black_planes, /* number of planes to send for each of CMY/RGB */ - j, - k, - pixels, /* number of pixels transferred to bit planes */ - planes; /* number of planes to send */ - eprn_Octet - comp_mask = 0, /* 'bits_per_component' 1s in the lowest part */ - pixel_mask = 0, /* 'depth' 1s in the lowest part */ - *ptr[8]; /* pointers into planes (next octet to write to) */ - - /* Number of planes to send */ - black_planes = eprn_bits_for_levels(dev->eprn.black_levels); - non_black_planes = eprn_bits_for_levels(dev->eprn.non_black_levels); - planes = black_planes + 3*non_black_planes; - - /* Initialize the bit plane pointers */ - for (j = 0; j < planes; j++) ptr[j] = plane[j].str; - - /* Determine some bit masks */ - for (j = 0; j < dev->color_info.depth; j++) - pixel_mask = (pixel_mask << 1) | 1; - for (j = 0; j < dev->eprn.bits_per_colorant; j++) - comp_mask = (comp_mask << 1) | 1; - - /* Copy from 'line' to 'plane[]', converting Z format to XY format */ - pixels = 0; - k = 0; /* Next octet index in the input line */ - while (k < length) { - int l, m, p; - - /* Initialize plane storage if it's a new output octet */ - if (pixels % 8 == 0) for (j = 0; j < planes; j++) *ptr[j] = 0; - - /* Loop over pixels within the input octet, starting at the leftmost - pixel (highest-order bits) */ - p = 8/dev->color_info.depth - 1; - do { - eprn_Octet comp; - - /* Extract pixel */ - pixel = (line[k] >> p*dev->color_info.depth) & pixel_mask; - - /* Extract components from the pixel and distribute each over its planes - */ - comp = pixel & comp_mask; /* black */ - for (j = 0; j < black_planes; j++) { - *ptr[j] = (*ptr[j] << 1) | comp & 1; - comp >>= 1; - } - if (non_black_planes > 0) for (l = 1; l < 4; l++) { - comp = (pixel >> l*dev->eprn.bits_per_colorant) & comp_mask; - for (m = 0; m < non_black_planes; m++, j++) { - *ptr[j] = (*ptr[j] << 1) | comp & 1; - comp >>= 1; - } - } - - pixels++; - p--; - } while (p >= 0); - k++; - - /* Increase plane pointers if an output octet boundary has been reached */ - if (pixels % 8 == 0) for (j = 0; j < planes; j++) ptr[j]++; - } - - eprn_finalize(dev->eprn.colour_model == eprn_DeviceRGB, - dev->eprn.non_black_levels, planes, plane, ptr, pixels); - - return; -} - -/****************************************************************************** - - Function: split_line_ge8 - - This split_line function has the following restrictions: - - The pixmap depth must be a multiple of 8. - - There may be at most 8 bits per colorant. - (Hence the depth is at most 32.) - - 'length' must be divisible by depth/8. - -******************************************************************************/ - -static void split_line_ge8(eprn_Device *dev, const eprn_Octet *line, - int length, eprn_OctetString plane[]) -{ - gx_color_index - pixel; - int - black_planes, /* number of planes to send for black */ - non_black_planes, /* number of planes to send for each of CMY/RGB */ - j, - k, - octets_per_pixel = dev->color_info.depth/8, - pixels, /* number of pixels transferred to bit planes */ - planes; /* number of planes to send */ - eprn_Octet - comp_mask = 0, /* bits_per_component 1s in the lowest part */ - *ptr[32]; /* pointers into planes (next octet to write to) */ - - /* Number of planes to send */ - black_planes = eprn_bits_for_levels(dev->eprn.black_levels); - non_black_planes = eprn_bits_for_levels(dev->eprn.non_black_levels); - planes = black_planes + 3*non_black_planes; - - /* Initialize the bit plane pointers */ - for (j = 0; j < planes; j++) ptr[j] = plane[j].str; - - /* Determine the component mask */ - for (j = 0; j < dev->eprn.bits_per_colorant; j++) - comp_mask = (comp_mask << 1) | 1; - - /* Copy from 'line' to 'plane[]', converting Z format to XY format */ - pixels = 0; - k = 0; /* Next octet index in the input line */ - while (k < length) { - eprn_Octet comp; - int l, m; - - /* Initialize plane storage if it's a new octet */ - if (pixels % 8 == 0) for (j = 0; j < planes; j++) *ptr[j] = 0; - - /* Reconstruct pixel from several octets */ - j = 0; - pixel = line[k]; - do { - j++; k++; - if (j >= octets_per_pixel) break; - pixel = (pixel << 8) | line[k]; /* MSB (Big Endian) */ - } while (1); - - /* Split and distribute over planes */ - comp = pixel & comp_mask; /* black */ - for (j = 0; j < black_planes; j++) { - *ptr[j] = (*ptr[j] << 1) | comp & 1; - comp >>= 1; - } - for (l = 1; l < 4; l++) { - comp = (pixel >> l*dev->eprn.bits_per_colorant) & comp_mask; - for (m = 0; m < non_black_planes; m++, j++) { - *ptr[j] = (*ptr[j] << 1) | comp & 1; - comp >>= 1; - } - } - - pixels++; - - /* Increase plane pointers if an octet boundary has been reached */ - if (pixels % 8 == 0) for (j = 0; j < planes; j++) ptr[j]++; - } - - eprn_finalize(dev->eprn.colour_model == eprn_DeviceRGB, - dev->eprn.non_black_levels, planes, plane, ptr, pixels); - - return; -} - -/****************************************************************************** - - Function: split_line_3or4x1 - - This function is a split_line() implementation for a non-monochrome colour - model (3 or 4 components) with 1 bit per component. - -******************************************************************************/ - -static void split_line_3or4x1(eprn_Device *dev, const eprn_Octet *line, - int length, eprn_OctetString plane[]) -{ - int - from = (dev->eprn.colour_model == eprn_DeviceRGB || - dev->eprn.colour_model == eprn_DeviceCMY? 1: 0), - j, - k, - l; - eprn_Octet *ptr[4]; /* pointers into planes, indexed KCMY/-RGB */ - - ptr[0] = NULL; /* defensive programming */ - for (j = from; j < 4; j++) ptr[j] = plane[j-from].str; - - /* Loop over the input line, taking four octets (8 pixels) at a time, as far - as available, and split them into four output octets, one for each - colorant. - */ - k = 0; - while (k < length) { - eprn_Octet octet[4] = {0, 0, 0, 0}; - - for (l = 0; l < 4 && k < length; l++, k++) { - eprn_Octet part; -#define treat_quartet() \ - octet[COLORANT_0_INDEX] <<= 1; \ - if (part & COLORANT_0_BIT) octet[COLORANT_0_INDEX] |= 1; \ - octet[COLORANT_1_INDEX] <<= 1; \ - if (part & COLORANT_1_BIT) octet[COLORANT_1_INDEX] |= 1; \ - octet[COLORANT_2_INDEX] <<= 1; \ - if (part & COLORANT_2_BIT) octet[COLORANT_2_INDEX] |= 1; \ - octet[COLORANT_3_INDEX] <<= 1; \ - if (part & COLORANT_3_BIT) octet[COLORANT_3_INDEX] |= 1; - - /* Upper four bits */ - part = (line[k] >> 4) & 0x0F; - treat_quartet() - - /* Lower four bits */ - part = line[k] & 0x0F; - treat_quartet() - -#undef treat_quartet - } - if (l < 4) { - for (j = from; j < 4; j++) octet[j] <<= 8 - 2*l; - if (dev->eprn.colour_model == eprn_DeviceRGB) { - /* Add white in the last 8 - 2*l pixels */ - for (j = 1; j < 4; j++) { - int k; - /* We add two pixels at a time */ - for (k = 3 - l; k >= 0; k--) octet[j] |= 0x03 << k; - } - } - } - for (j = from; j < 4; j++) *(ptr[j]++) = octet[j]; - } - - /* Set the lengths of the bit plane strings */ - for (j = 0; j < dev->eprn.output_planes; j++) { - if (length == 0) plane[j].length = 0; - else plane[j].length = ptr[from + j] - plane[j].str; - } - - return; -} - -/****************************************************************************** - - Function: split_line_4x2 - - This is a split_line() implementation for 4 colour components (i.e., CMYK) - with 3 or 4 levels each (2 bit planes to send for each component). - -******************************************************************************/ - -static void split_line_4x2(eprn_Device *dev, const eprn_Octet *line, - int length, eprn_OctetString plane[]) -{ - gx_color_index - pixel; - int - j, - k; - eprn_Octet - *ptr[8]; /* pointers into planes (next octet to write to) */ - - /* Initialize the bit plane pointers */ - for (j = 0; j < 8; j++) ptr[j] = plane[j].str; - - /* Copy from 'line' to 'plane[]', converting Z format to XY format */ - for (k = 0; k < length; k++) { - /* k is the index of the next octet in the input line and the number of - pixels processed so far. */ - - /* Initialize plane storage if it's a new octet */ - if (k % 8 == 0) for (j = 0; j < 8; j++) *ptr[j] = 0; - - /* Fetch pixel */ - pixel = line[k]; - - /* Split and distribute over planes */ - *ptr[0] = (*ptr[0] << 1) | pixel & 0x01; -#define assign_bit(index) \ - *ptr[index] = (*ptr[index] << 1) | (pixel >> index) & 0x01 - assign_bit(1); - assign_bit(2); - assign_bit(3); - assign_bit(4); - assign_bit(5); - assign_bit(6); - assign_bit(7); -#undef assign_bit - - /* Increase plane pointers if an output octet boundary has been reached */ - if (k % 8 == 7) for (j = 0; j < 8; j++) ptr[j]++; - } - - /* Execute remaining left shifts in the last octet of the output planes when - the number of pixels is not a multiple of 8 */ - k = length % 8; - if (k != 0) { - int shift = 8 - k; - for (j = 0; j < 8; j++) - *(ptr[j]++) = *ptr[j] << shift; - } - - /* Set the lengths of the bit plane strings */ - for (j = 0; j < 8; j++) { - if (length == 0) plane[j].length = 0; - else plane[j].length = ptr[j] - plane[j].str; - } - - return; -} - -/****************************************************************************** - - Function: eprn_fetch_scan_line - - If there is a next scan line with y coordinate 'dev->eprn.next_y', this - function fetches it into '*line' and returns zero. Otherwise the function - returns a non-zero value. - - The storage allocated for 'line->str' must be at least of size - 'dev->eprn.octets_per_line'. - - On success, the 'length' field in 'line' does not include trailing zero - pixels. - -******************************************************************************/ - -int eprn_fetch_scan_line(eprn_Device *dev, eprn_OctetString *line) -{ - int rc; - const eprn_Octet *str; - - rc = gdev_prn_copy_scan_lines((gx_device_printer *)dev, dev->eprn.next_y, - line->str, dev->eprn.octets_per_line); - /* gdev_prn_copy_scan_lines() returns the number of scan lines it fetched - or a negative value on error. The number of lines to fetch is the value - of the last argument divided by the length of a single line, hence in - this case 1. */ - if (rc != 1) return 1; - - /* Set the length to ignore trailing zero octets in the scan line */ - str = line->str + (dev->eprn.octets_per_line - 1); - while (str > line->str && *str == 0) str--; - if (*str == 0) line->length = 0; - else line->length = str - line->str + 1; - - /* Ensure we have an integral number of pixels in the line */ - if (dev->color_info.depth > 8) { - int rem; - unsigned int octets_per_pixel = dev->color_info.depth/8; - /* If the depth is larger than 8, it is a multiple of 8. */ - rem = line->length % octets_per_pixel; - if (rem != 0) line->length += octets_per_pixel - rem; - } - -#if 0 && defined(EPRN_TRACE) - if (gs_debug_c(EPRN_TRACE_CHAR)) { - int j; - dlprintf("! eprn_fetch_scan_line(): Fetched "); - if (line->length == 0) dprintf("empty scan line."); - else { - dprintf("scan line: 0x"); - for (j = 0; j < line->length; j++) dprintf1("%02X", line->str[j]); - } - dlprintf("\n"); - } -#endif - - return 0; -} - -/****************************************************************************** - - Function: eprn_get_planes - - For the description of this function, see gdeveprn.h. - -******************************************************************************/ - -int eprn_get_planes(eprn_Device *dev, eprn_OctetString bitplanes[]) -{ - eprn_OctetString *line; /* where to copy the scan line from the prn device */ - int - j, - rc; - - /* Avoid a copying step for a depth of 1 */ - if (dev->color_info.depth == 1) line = bitplanes; - else line = &dev->eprn.scan_line; - - /* Fetch the scan line if available */ - if (dev->eprn.intensity_rendering == eprn_IR_FloydSteinberg && - dev->eprn.next_y == 0) return 1; - rc = eprn_fetch_scan_line(dev, line); - if (rc == 0) dev->eprn.next_y++; - else { - if (dev->eprn.intensity_rendering != eprn_IR_FloydSteinberg) return 1; - dev->eprn.next_y = 0; - } - - if (dev->color_info.depth == 1) return 0; - - if (dev->eprn.intensity_rendering == eprn_IR_FloydSteinberg) { - eprn_OctetString tmp; - - eprn_split_FS(&dev->eprn.next_scan_line, &dev->eprn.scan_line, - dev->eprn.octets_per_line, - dev->eprn.colour_model, - dev->eprn.black_levels, dev->eprn.non_black_levels, - bitplanes); - - /* Switch 'next_scan_line' to refer to what is currently 'scan_line' */ - tmp = dev->eprn.next_scan_line; - dev->eprn.next_scan_line = dev->eprn.scan_line; - dev->eprn.scan_line = tmp; - } - else { - /* Here we split multi-bit pixels which are already adapted to the - printer's capabilities. - - All the functions called here have the following signature: - - static void split_line...(eprn_Device *dev, const eprn_Octet *line, - int length, eprn_OctetString plane[]) - - Such a "split_line implementation" must take the scan line of length - 'length', pointed to by 'line', split it into bit planes according to - the state of 'dev', and return these planes via 'plane'. The length - fields of the planes must be set. Trailing zero octets should not be - removed because it's done here afterwards anyway. - */ - - if (dev->eprn.colour_model == eprn_DeviceGray) - split_line_le8(dev, line->str, line->length, bitplanes); - else { - if (dev->eprn.bits_per_colorant == 1) { -#ifndef EPRN_TRAILING_BIT_BUG_FIXED - if (dev->eprn.colour_model == eprn_DeviceRGB && - line->length == dev->eprn.octets_per_line) { - /* At least gs 6.01 and 6.50 sometimes generate pixel lines where the - last pixel is not white but black (last octet in 'line' is 0xE0 - instead of 0xEE; with pcl3 it shows up for A6 and A4, but not for - A3, A5, US Letter, or US Legal). - I'm overwriting it with white. */ -#ifdef EPRN_TRACE - if (gs_debug_c(EPRN_TRACE_CHAR)) { - static bool already_noted = false; - if (!already_noted && line->str[line->length - 1] != 0xEE) { - dlprintf1("! eprn_get_planes(): " - "Line-terminating octet is 0x%02X.\n", - line->str[line->length - 1]); - already_noted = true; - } - } -#endif /* EPRN_TRACE */ - line->str[line->length - 1] |= RED_BIT | GREEN_BIT | BLUE_BIT; - } -#endif /* EPRN_TRAILING_BIT_BUG_FIXED */ - split_line_3or4x1(dev, line->str, line->length, bitplanes); - } - else if (dev->eprn.bits_per_colorant == 2 && dev->eprn.black_levels > 2 && - dev->eprn.non_black_levels > 2) - split_line_4x2(dev, line->str, line->length, bitplanes); - else if (dev->color_info.depth < 8) - split_line_le8(dev, line->str, line->length, bitplanes); - else split_line_ge8(dev, line->str, line->length, bitplanes); - } - } - - /* Reduce the lengths of the individual bit planes to not include trailing - zero octets */ - for (j = 0; j < dev->eprn.output_planes; j++) { - if (bitplanes[j].length > 0) { - const eprn_Octet *str = bitplanes[j].str + (bitplanes[j].length - 1); - while (str > bitplanes[j].str && *str == 0) str--; - if (*str == 0) bitplanes[j].length = 0; - else bitplanes[j].length = (str - bitplanes[j].str) + 1; - } - } - - return 0; -} |