📄 eprnrend.c
字号:
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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -