123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798 |
- /* Copyright (C) 1997, 1998, 1999 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: gdevdgbr.c,v 1.2 2000/09/19 19:00:12 lpd Exp $ */
- /* Default implementation of device get_bits[_rectangle] */
- #include "memory_.h"
- #include "gx.h"
- #include "gserrors.h"
- #include "gxdevice.h"
- #include "gxdevmem.h"
- #include "gxgetbit.h"
- #include "gxlum.h"
- #include "gdevmem.h"
- int
- gx_no_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
- {
- return_error(gs_error_unknownerror);
- }
- int
- gx_default_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
- { /*
- * Hand off to get_bits_rectangle, being careful to avoid a
- * possible recursion loop.
- */
- dev_proc_get_bits((*save_get_bits)) = dev_proc(dev, get_bits);
- gs_int_rect rect;
- gs_get_bits_params_t params;
- int code;
- rect.p.x = 0, rect.p.y = y;
- rect.q.x = dev->width, rect.q.y = y + 1;
- params.options =
- (actual_data ? GB_RETURN_POINTER : 0) | GB_RETURN_COPY |
- (GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD |
- /* No depth specified, we always use native colors. */
- GB_PACKING_CHUNKY | GB_COLORS_NATIVE | GB_ALPHA_NONE);
- params.x_offset = 0;
- params.raster = bitmap_raster(dev->width * dev->color_info.depth);
- params.data[0] = data;
- set_dev_proc(dev, get_bits, gx_no_get_bits);
- code = (*dev_proc(dev, get_bits_rectangle))
- (dev, &rect, ¶ms, NULL);
- if (actual_data)
- *actual_data = params.data[0];
- set_dev_proc(dev, get_bits, save_get_bits);
- return code;
- }
- /*
- * Determine whether we can satisfy a request by simply using the stored
- * representation. dev is used only for color_info.{num_components, depth}.
- */
- private bool
- requested_includes_stored(const gx_device *dev,
- const gs_get_bits_params_t *requested,
- const gs_get_bits_params_t *stored)
- {
- gs_get_bits_options_t both = requested->options & stored->options;
- if (!(both & GB_PACKING_ALL))
- return false;
- if (stored->options & GB_SELECT_PLANES) {
- /*
- * The device only provides a subset of the planes.
- * Make sure it provides all the requested ones.
- */
- int i;
- int n = (stored->options & GB_PACKING_BIT_PLANAR ?
- dev->color_info.depth : dev->color_info.num_components);
- if (!(requested->options & GB_SELECT_PLANES) ||
- !(both & (GB_PACKING_PLANAR || GB_PACKING_BIT_PLANAR))
- )
- return false;
- for (i = 0; i < n; ++i)
- if (requested->data[i] && !stored->data[i])
- return false;
- }
- if (both & GB_COLORS_NATIVE)
- return true;
- if (both & GB_COLORS_STANDARD_ALL) {
- if ((both & GB_ALPHA_ALL) && (both & GB_DEPTH_ALL))
- return true;
- }
- return false;
- }
- /*
- * Try to implement get_bits_rectangle by returning a pointer.
- * Note that dev is used only for computing the default raster
- * and for color_info.depth.
- * This routine does not check x or h for validity.
- */
- int
- gx_get_bits_return_pointer(gx_device * dev, int x, int h,
- gs_get_bits_params_t *params,
- const gs_get_bits_params_t *stored,
- byte * stored_base)
- {
- gs_get_bits_options_t options = params->options;
- gs_get_bits_options_t both = options & stored->options;
- if (!(options & GB_RETURN_POINTER) ||
- !requested_includes_stored(dev, params, stored)
- )
- return -1;
- /*
- * See whether we can return the bits in place. Note that even if
- * OFFSET_ANY isn't set, x_offset and x don't have to be equal: their
- * bit offsets only have to match modulo align_bitmap_mod * 8 (to
- * preserve alignment) if ALIGN_ANY isn't set, or mod 8 (since
- * byte alignment is always required) if ALIGN_ANY is set.
- */
- {
- int depth = dev->color_info.depth;
- /*
- * For PLANAR devices, we assume that each plane consists of
- * depth/num_components bits. This is wrong in general, but if
- * the device wants something else, it should implement
- * get_bits_rectangle itself.
- */
- uint dev_raster =
- (both & GB_PACKING_CHUNKY ?
- gx_device_raster(dev, true) :
- both & GB_PACKING_PLANAR ?
- bitmap_raster(dev->color_info.depth /
- dev->color_info.num_components * dev->width) :
- both & GB_PACKING_BIT_PLANAR ?
- bitmap_raster(dev->width) :
- 0 /* not possible */);
- uint raster =
- (options & (GB_RASTER_STANDARD | GB_RASTER_ANY) ? dev_raster :
- params->raster);
- byte *base;
- if (h <= 1 || raster == dev_raster) {
- int x_offset =
- (options & GB_OFFSET_ANY ? x :
- options & GB_OFFSET_0 ? 0 : params->x_offset);
- if (x_offset == x) {
- base = stored_base;
- params->x_offset = x;
- } else {
- uint align_mod =
- (options & GB_ALIGN_ANY ? 8 : align_bitmap_mod * 8);
- int bit_offset = x - x_offset;
- int bytes;
- if (bit_offset & (align_mod - 1))
- return -1; /* can't align */
- if (depth & (depth - 1)) {
- /* step = lcm(depth, align_mod) */
- int step = depth / igcd(depth, align_mod) * align_mod;
- bytes = bit_offset / step * step;
- } else {
- /* Use a faster algorithm if depth is a power of 2. */
- bytes = bit_offset & (-depth & -align_mod);
- }
- base = stored_base + arith_rshift(bytes, 3);
- params->x_offset = (bit_offset - bytes) / depth;
- }
- params->options =
- GB_ALIGN_STANDARD | GB_RETURN_POINTER | GB_RASTER_STANDARD |
- (stored->options & ~GB_PACKING_ALL) /*see below for PACKING*/ |
- (params->x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED);
- if (both & GB_PACKING_CHUNKY) {
- params->options |= GB_PACKING_CHUNKY;
- params->data[0] = base;
- } else {
- int n =
- (stored->options & GB_PACKING_BIT_PLANAR ?
- (params->options |= GB_PACKING_BIT_PLANAR,
- dev->color_info.depth) :
- (params->options |= GB_PACKING_PLANAR,
- dev->color_info.num_components));
- int i;
- for (i = 0; i < n; ++i)
- if (!(both & GB_SELECT_PLANES) || stored->data[i] != 0) {
- params->data[i] = base;
- base += dev_raster * dev->height;
- }
- }
- return 0;
- }
- }
- return -1;
- }
- /*
- * Implement gx_get_bits_copy (see below) for the case of converting
- * 4-bit CMYK to 24-bit RGB with standard mapping, used heavily by PCL.
- */
- private void
- gx_get_bits_copy_cmyk_1bit(byte *dest_line, uint dest_raster,
- const byte *src_line, uint src_raster,
- int src_bit, int w, int h)
- {
- for (; h > 0; dest_line += dest_raster, src_line += src_raster, --h) {
- const byte *src = src_line;
- byte *dest = dest_line;
- bool hi = (src_bit & 4) != 0; /* last nibble processed was hi */
- int i;
- for (i = w; i > 0; dest += 3, --i) {
- uint pixel =
- ((hi = !hi)? *src >> 4 : *src++ & 0xf);
- if (pixel & 1)
- dest[0] = dest[1] = dest[2] = 0;
- else {
- dest[0] = (byte)((pixel >> 3) - 1);
- dest[1] = (byte)(((pixel >> 2) & 1) - 1);
- dest[2] = (byte)(((pixel >> 1) & 1) - 1);
- }
- }
- }
- }
- /*
- * Convert pixels between representations, primarily for get_bits_rectangle.
- * stored indicates how the data are actually stored, and includes:
- * - one option from the GB_PACKING group;
- * - if h > 1, one option from the GB_RASTER group;
- * - optionally (and normally), GB_COLORS_NATIVE;
- * - optionally, one option each from the GB_COLORS_STANDARD, GB_DEPTH,
- * and GB_ALPHA groups.
- * Note that dev is used only for color mapping. This routine assumes that
- * the stored data are aligned.
- *
- * Note: this routine does not check x, w, h for validity.
- *
- * The code for converting between standard and native colors has been
- * factored out into single-use procedures strictly for readability.
- * A good optimizing compiler would compile them in-line.
- */
- private int
- gx_get_bits_std_to_native(P10(gx_device * dev, int x, int w, int h,
- gs_get_bits_params_t * params,
- const gs_get_bits_params_t *stored,
- const byte * src_base, uint dev_raster,
- int x_offset, uint raster)),
- gx_get_bits_native_to_std(P11(gx_device * dev, int x, int w, int h,
- gs_get_bits_params_t * params,
- const gs_get_bits_params_t *stored,
- const byte * src_base, uint dev_raster,
- int x_offset, uint raster, uint std_raster));
- int
- gx_get_bits_copy(gx_device * dev, int x, int w, int h,
- gs_get_bits_params_t * params,
- const gs_get_bits_params_t *stored,
- const byte * src_base, uint dev_raster)
- {
- gs_get_bits_options_t options = params->options;
- gs_get_bits_options_t stored_options = stored->options;
- int x_offset = (options & GB_OFFSET_0 ? 0 : params->x_offset);
- int depth = dev->color_info.depth;
- int bit_x = x * depth;
- const byte *src = src_base;
- /*
- * If the stored representation matches a requested representation,
- * we can copy the data without any transformations.
- */
- bool direct_copy = requested_includes_stored(dev, params, stored);
- int code = 0;
- /*
- * The request must include either GB_PACKING_CHUNKY or
- * GB_PACKING_PLANAR + GB_SELECT_PLANES, GB_RETURN_COPY,
- * and an offset and raster specification. In the planar case,
- * the request must include GB_ALIGN_STANDARD, the stored
- * representation must include GB_PACKING_CHUNKY, and both must
- * include GB_COLORS_NATIVE.
- */
- if ((~options & GB_RETURN_COPY) ||
- !(options & (GB_OFFSET_0 | GB_OFFSET_SPECIFIED)) ||
- !(options & (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED))
- )
- return_error(gs_error_rangecheck);
- if (options & GB_PACKING_CHUNKY) {
- byte *data = params->data[0];
- int end_bit = (x_offset + w) * depth;
- uint std_raster =
- (options & GB_ALIGN_STANDARD ? bitmap_raster(end_bit) :
- (end_bit + 7) >> 3);
- uint raster =
- (options & GB_RASTER_STANDARD ? std_raster : params->raster);
- int dest_bit_x = x_offset * depth;
- int skew = bit_x - dest_bit_x;
- /*
- * If the bit positions line up, use bytes_copy_rectangle.
- * Since bytes_copy_rectangle doesn't require alignment,
- * the bit positions only have to match within a byte,
- * not within align_bitmap_mod bytes.
- */
- if (!(skew & 7) && direct_copy) {
- int bit_w = w * depth;
- bytes_copy_rectangle(data + (dest_bit_x >> 3), raster,
- src + (bit_x >> 3), dev_raster,
- ((bit_x + bit_w + 7) >> 3) - (bit_x >> 3), h);
- } else if (direct_copy) {
- /*
- * Use the logic already in mem_mono_copy_mono to copy the
- * bits to the destination. We do this one line at a time,
- * to avoid having to allocate a line pointer table.
- */
- gx_device_memory tdev;
- byte *line_ptr = data;
- tdev.line_ptrs = &tdev.base;
- for (; h > 0; line_ptr += raster, src += dev_raster, --h) {
- /* Make sure the destination is aligned. */
- int align = ALIGNMENT_MOD(line_ptr, align_bitmap_mod);
- tdev.base = line_ptr - align;
- (*dev_proc(&mem_mono_device, copy_mono))
- ((gx_device *) & tdev, src, bit_x, dev_raster, gx_no_bitmap_id,
- dest_bit_x + (align << 3), 0, w, 1,
- (gx_color_index) 0, (gx_color_index) 1);
- }
- } else if (options & ~stored_options & GB_COLORS_NATIVE) {
- /* Convert standard colors to native. */
- code = gx_get_bits_std_to_native(dev, x, w, h, params, stored,
- src_base, dev_raster,
- x_offset, raster);
- options = params->options;
- } else {
- /* Convert native colors to standard. */
- code = gx_get_bits_native_to_std(dev, x, w, h, params, stored,
- src_base, dev_raster,
- x_offset, raster, std_raster);
- options = params->options;
- }
- params->options =
- (options & (GB_COLORS_ALL | GB_ALPHA_ALL)) | GB_PACKING_CHUNKY |
- (options & GB_COLORS_NATIVE ? 0 : options & GB_DEPTH_ALL) |
- (options & GB_ALIGN_STANDARD ? GB_ALIGN_STANDARD : GB_ALIGN_ANY) |
- GB_RETURN_COPY |
- (x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED) |
- (raster == std_raster ? GB_RASTER_STANDARD : GB_RASTER_SPECIFIED);
- } else if (!(~options &
- (GB_PACKING_PLANAR | GB_SELECT_PLANES | GB_ALIGN_STANDARD)) &&
- (stored_options & GB_PACKING_CHUNKY) &&
- ((options & stored_options) & GB_COLORS_NATIVE)
- ) {
- int num_planes = dev->color_info.num_components;
- int dest_depth = depth / num_planes;
- bits_plane_t source, dest;
- int plane = -1;
- int i;
- /* Make sure only one plane is being requested. */
- for (i = 0; i < num_planes; ++i)
- if (params->data[i] != 0) {
- if (plane >= 0)
- return_error(gs_error_rangecheck); /* > 1 plane */
- plane = i;
- }
- source.data.read = src_base;
- source.raster = dev_raster;
- source.depth = depth;
- source.x = x;
- dest.data.write = params->data[plane];
- dest.raster =
- (options & GB_RASTER_STANDARD ?
- bitmap_raster((x_offset + w) * dest_depth) : params->raster);
- dest.depth = dest_depth;
- dest.x = x_offset;
- return bits_extract_plane(&dest, &source,
- (num_planes - 1 - plane) * dest_depth,
- w, h);
- } else
- return_error(gs_error_rangecheck);
- return code;
- }
- /*
- * Convert standard colors to native. Note that the source
- * may have depths other than 8 bits per component.
- */
- private int
- gx_get_bits_std_to_native(gx_device * dev, int x, int w, int h,
- gs_get_bits_params_t * params,
- const gs_get_bits_params_t *stored,
- const byte * src_base, uint dev_raster,
- int x_offset, uint raster)
- {
- int depth = dev->color_info.depth;
- int dest_bit_offset = x_offset * depth;
- byte *dest_line = params->data[0] + (dest_bit_offset >> 3);
- int ncolors =
- (stored->options & GB_COLORS_RGB ? 3 :
- stored->options & GB_COLORS_CMYK ? 4 :
- stored->options & GB_COLORS_GRAY ? 1 : -1);
- int ncomp = ncolors +
- ((stored->options & (GB_ALPHA_FIRST | GB_ALPHA_LAST)) != 0);
- int src_depth = GB_OPTIONS_DEPTH(stored->options);
- int src_bit_offset = x * src_depth * ncomp;
- const byte *src_line = src_base + (src_bit_offset >> 3);
- gx_color_value src_max = (1 << src_depth) - 1;
- #define v2cv(value) ((ulong)(value) * gx_max_color_value / src_max)
- gx_color_value alpha_default = src_max;
- params->options &= ~GB_COLORS_ALL | GB_COLORS_NATIVE;
- for (; h > 0; dest_line += raster, src_line += dev_raster, --h) {
- int i;
- sample_load_declare_setup(src, sbit, src_line,
- src_bit_offset & 7, src_depth);
- sample_store_declare_setup(dest, dbit, dbyte, dest_line,
- dest_bit_offset & 7, depth);
- for (i = 0; i < w; ++i) {
- int j;
- gx_color_value v[4], va = alpha_default;
- gx_color_index pixel;
- /* Fetch the source data. */
- if (stored->options & GB_ALPHA_FIRST) {
- sample_load_next16(va, src, sbit, src_depth);
- va = v2cv(va);
- }
- for (j = 0; j < ncolors; ++j) {
- gx_color_value vj;
- sample_load_next16(vj, src, sbit, src_depth);
- v[j] = v2cv(vj);
- }
- if (stored->options & GB_ALPHA_LAST) {
- sample_load_next16(va, src, sbit, src_depth);
- va = v2cv(va);
- }
- /* Convert and store the pixel value. */
- switch (ncolors) {
- case 1:
- v[2] = v[1] = v[0];
- case 3:
- pixel = (*dev_proc(dev, map_rgb_alpha_color))
- (dev, v[0], v[1], v[2], va);
- break;
- case 4:
- /****** NO ALPHA FOR CMYK ******/
- pixel = (*dev_proc(dev, map_cmyk_color))
- (dev, v[0], v[1], v[2], v[3]);
- break;
- default:
- return_error(gs_error_rangecheck);
- }
- sample_store_next32(pixel, dest, dbit, depth, dbyte);
- }
- sample_store_flush(dest, dbit, depth, dbyte);
- }
- return 0;
- }
- /*
- * Convert native colors to standard. Only GB_DEPTH_8 is supported.
- */
- private int
- gx_get_bits_native_to_std(gx_device * dev, int x, int w, int h,
- gs_get_bits_params_t * params,
- const gs_get_bits_params_t *stored,
- const byte * src_base, uint dev_raster,
- int x_offset, uint raster, uint std_raster)
- {
- int depth = dev->color_info.depth;
- int src_bit_offset = x * depth;
- const byte *src_line = src_base + (src_bit_offset >> 3);
- gs_get_bits_options_t options = params->options;
- int ncomp =
- (options & (GB_ALPHA_FIRST | GB_ALPHA_LAST) ? 4 : 3);
- byte *dest_line = params->data[0] + x_offset * ncomp;
- byte *mapped[16];
- int dest_bytes;
- int i;
- if (!(options & GB_DEPTH_8)) {
- /*
- * We don't support general depths yet, or conversion between
- * different formats. Punt.
- */
- return_error(gs_error_rangecheck);
- }
- /* Pick the representation that's most likely to be useful. */
- if (options & GB_COLORS_RGB)
- params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_RGB,
- dest_bytes = 3;
- else if (options & GB_COLORS_CMYK)
- params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_CMYK,
- dest_bytes = 4;
- else if (options & GB_COLORS_GRAY)
- params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_GRAY,
- dest_bytes = 1;
- else
- return_error(gs_error_rangecheck);
- /* Recompute the destination raster based on the color space. */
- if (options & GB_RASTER_STANDARD) {
- uint end_byte = (x_offset + w) * dest_bytes;
- raster = std_raster =
- (options & GB_ALIGN_STANDARD ?
- bitmap_raster(end_byte << 3) : end_byte);
- }
- /* Check for the one special case we care about. */
- if (((options & (GB_COLORS_RGB | GB_ALPHA_FIRST | GB_ALPHA_LAST))
- == GB_COLORS_RGB) &&
- dev_proc(dev, map_color_rgb) == cmyk_1bit_map_color_rgb) {
- gx_get_bits_copy_cmyk_1bit(dest_line, raster,
- src_line, dev_raster,
- src_bit_offset & 7, w, h);
- return 0;
- }
- if (options & (GB_ALPHA_FIRST | GB_ALPHA_LAST))
- ++dest_bytes;
- /* Clear the color translation cache. */
- for (i = (depth > 4 ? 16 : 1 << depth); --i >= 0; )
- mapped[i] = 0;
- for (; h > 0; dest_line += raster, src_line += dev_raster, --h) {
- sample_load_declare_setup(src, bit, src_line,
- src_bit_offset & 7, depth);
- byte *dest = dest_line;
- for (i = 0; i < w; ++i) {
- gx_color_index pixel = 0;
- gx_color_value rgba[4];
- sample_load_next32(pixel, src, bit, depth);
- if (pixel < 16) {
- if (mapped[pixel]) {
- /* Use the value from the cache. */
- memcpy(dest, mapped[pixel], dest_bytes);
- dest += dest_bytes;
- continue;
- }
- mapped[pixel] = dest;
- }
- (*dev_proc(dev, map_color_rgb_alpha)) (dev, pixel, rgba);
- if (options & GB_ALPHA_FIRST)
- *dest++ = gx_color_value_to_byte(rgba[3]);
- /* Convert to the requested color space. */
- if (options & GB_COLORS_RGB) {
- dest[0] = gx_color_value_to_byte(rgba[0]);
- dest[1] = gx_color_value_to_byte(rgba[1]);
- dest[2] = gx_color_value_to_byte(rgba[2]);
- dest += 3;
- } else if (options & GB_COLORS_CMYK) {
- /* Use the standard RGB to CMYK algorithm, */
- /* with maximum black generation and undercolor removal. */
- gx_color_value white = max(rgba[0], max(rgba[1], rgba[2]));
- dest[0] = gx_color_value_to_byte(white - rgba[0]);
- dest[1] = gx_color_value_to_byte(white - rgba[1]);
- dest[2] = gx_color_value_to_byte(white - rgba[2]);
- dest[3] = gx_color_value_to_byte(gx_max_color_value - white);
- dest += 4;
- } else { /* GB_COLORS_GRAY */
- /* Use the standard RGB to Gray algorithm. */
- *dest++ = gx_color_value_to_byte(
- ((rgba[0] * (ulong) lum_red_weight) +
- (rgba[1] * (ulong) lum_green_weight) +
- (rgba[2] * (ulong) lum_blue_weight) +
- (lum_all_weights / 2))
- / lum_all_weights);
- }
- if (options & GB_ALPHA_LAST)
- *dest++ = gx_color_value_to_byte(rgba[3]);
- }
- }
- return 0;
- }
- /* ------ Default implementations of get_bits_rectangle ------ */
- int
- gx_no_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
- gs_get_bits_params_t * params, gs_int_rect ** unread)
- {
- return_error(gs_error_unknownerror);
- }
- int
- gx_default_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
- gs_get_bits_params_t * params, gs_int_rect ** unread)
- {
- dev_proc_get_bits_rectangle((*save_get_bits_rectangle)) =
- dev_proc(dev, get_bits_rectangle);
- int depth = dev->color_info.depth;
- uint min_raster = (dev->width * depth + 7) >> 3;
- gs_get_bits_options_t options = params->options;
- int code;
- /* Avoid a recursion loop. */
- set_dev_proc(dev, get_bits_rectangle, gx_no_get_bits_rectangle);
- /*
- * If the parameters are right, try to call get_bits directly. Note
- * that this may fail if a device only implements get_bits_rectangle
- * (not get_bits) for a limited set of options. Note also that this
- * must handle the case of the recursive call from within
- * get_bits_rectangle (see below): because of this, and only because
- * of this, it must handle partial scan lines.
- */
- if (prect->q.y == prect->p.y + 1 &&
- !(~options &
- (GB_RETURN_COPY | GB_PACKING_CHUNKY | GB_COLORS_NATIVE)) &&
- (options & (GB_ALIGN_STANDARD | GB_ALIGN_ANY)) &&
- ((options & (GB_OFFSET_0 | GB_OFFSET_ANY)) ||
- ((options & GB_OFFSET_SPECIFIED) && params->x_offset == 0)) &&
- ((options & (GB_RASTER_STANDARD | GB_RASTER_ANY)) ||
- ((options & GB_RASTER_SPECIFIED) &&
- params->raster >= min_raster)) &&
- unread == NULL
- ) {
- byte *data = params->data[0];
- byte *row = data;
- if (!(prect->p.x == 0 && prect->q.x == dev->width)) {
- /* Allocate an intermediate row buffer. */
- row = gs_alloc_bytes(dev->memory, min_raster,
- "gx_default_get_bits_rectangle");
- if (row == 0) {
- code = gs_note_error(gs_error_VMerror);
- goto ret;
- }
- }
- code = (*dev_proc(dev, get_bits))
- (dev, prect->p.y, row, ¶ms->data[0]);
- if (code >= 0) {
- if (row != data) {
- if (prect->p.x == 0 && params->data[0] != row) {
- /*
- * get_bits returned an appropriate pointer: we can
- * avoid doing any copying.
- */
- DO_NOTHING;
- } else {
- /* Copy the partial row into the supplied buffer. */
- int width_bits = (prect->q.x - prect->p.x) * depth;
- gx_device_memory tdev;
- tdev.width = width_bits;
- tdev.height = 1;
- tdev.line_ptrs = &tdev.base;
- tdev.base = data;
- code = (*dev_proc(&mem_mono_device, copy_mono))
- ((gx_device *) & tdev, params->data[0], prect->p.x * depth,
- min_raster, gx_no_bitmap_id, 0, 0, width_bits, 1,
- (gx_color_index) 0, (gx_color_index) 1);
- params->data[0] = data;
- }
- gs_free_object(dev->memory, row,
- "gx_default_get_bits_rectangle");
- }
- params->options =
- GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_PACKING_CHUNKY |
- GB_ALPHA_NONE | GB_COLORS_NATIVE | GB_RASTER_STANDARD |
- (params->data[0] == data ? GB_RETURN_COPY : GB_RETURN_POINTER);
- goto ret;
- }
- } {
- /* Do the transfer row-by-row using a buffer. */
- int x = prect->p.x, w = prect->q.x - x;
- int bits_per_pixel = depth;
- byte *row;
- if (options & GB_COLORS_STANDARD_ALL) {
- /*
- * Make sure the row buffer can hold the standard color
- * representation, in case the device decides to use it.
- */
- int bpc = GB_OPTIONS_MAX_DEPTH(options);
- int nc =
- (options & GB_COLORS_CMYK ? 4 :
- options & GB_COLORS_RGB ? 3 : 1) +
- (options & (GB_ALPHA_ALL - GB_ALPHA_NONE) ? 1 : 0);
- int bpp = bpc * nc;
- if (bpp > bits_per_pixel)
- bits_per_pixel = bpp;
- }
- row = gs_alloc_bytes(dev->memory, (bits_per_pixel * w + 7) >> 3,
- "gx_default_get_bits_rectangle");
- if (row == 0) {
- code = gs_note_error(gs_error_VMerror);
- } else {
- uint dev_raster = gx_device_raster(dev, true);
- uint raster =
- (options & GB_RASTER_SPECIFIED ? params->raster :
- options & GB_ALIGN_STANDARD ? bitmap_raster(depth * w) :
- (depth * w + 7) >> 3);
- gs_int_rect rect;
- gs_get_bits_params_t copy_params;
- gs_get_bits_options_t copy_options =
- (GB_ALIGN_STANDARD | GB_ALIGN_ANY) |
- (GB_RETURN_COPY | GB_RETURN_POINTER) |
- (GB_OFFSET_0 | GB_OFFSET_ANY) |
- (GB_RASTER_STANDARD | GB_RASTER_ANY) | GB_PACKING_CHUNKY |
- GB_COLORS_NATIVE | (options & (GB_DEPTH_ALL | GB_COLORS_ALL)) |
- GB_ALPHA_ALL;
- byte *dest = params->data[0];
- int y;
- rect.p.x = x, rect.q.x = x + w;
- code = 0;
- for (y = prect->p.y; y < prect->q.y; ++y) {
- rect.p.y = y, rect.q.y = y + 1;
- copy_params.options = copy_options;
- copy_params.data[0] = row;
- code = (*save_get_bits_rectangle)
- (dev, &rect, ©_params, NULL);
- if (code < 0)
- break;
- if (copy_params.options & GB_OFFSET_0)
- copy_params.x_offset = 0;
- params->data[0] = dest + (y - prect->p.y) * raster;
- code = gx_get_bits_copy(dev, copy_params.x_offset, w, 1,
- params, ©_params,
- copy_params.data[0], dev_raster);
- if (code < 0)
- break;
- }
- gs_free_object(dev->memory, row, "gx_default_get_bits_rectangle");
- params->data[0] = dest;
- }
- }
- ret:set_dev_proc(dev, get_bits_rectangle, save_get_bits_rectangle);
- return (code < 0 ? code : 0);
- }
- /* ------ Debugging printout ------ */
- #ifdef DEBUG
- void
- debug_print_gb_options(gx_bitmap_format_t options)
- {
- static const char *const option_names[] = {
- GX_BITMAP_FORMAT_NAMES
- };
- const char *prev = " ";
- int i;
- dlprintf1("0x%lx", (ulong) options);
- for (i = 0; i < sizeof(options) * 8; ++i)
- if ((options >> i) & 1) {
- dprintf2("%c%s",
- (!memcmp(prev, option_names[i], 3) ? '|' : ','),
- option_names[i]);
- prev = option_names[i];
- }
- dputc('\n');
- }
- void
- debug_print_gb_planes(const gs_get_bits_params_t * params, int num_planes)
- {
- gs_get_bits_options_t options = params->options;
- int i;
- debug_print_gb_options(options);
- for (i = 0; i < num_planes; ++i)
- dprintf2("data[%d]=0x%lx ", i, (ulong)params->data[i]);
- if (options & GB_OFFSET_SPECIFIED)
- dprintf1("x_offset=%d ", params->x_offset);
- if (options & GB_RASTER_SPECIFIED)
- dprintf1("raster=%u", params->raster);
- dputc('\n');
- }
- void
- debug_print_gb_params(const gs_get_bits_params_t * params)
- {
- debug_print_gb_planes(params, 1);
- }
- #endif /* DEBUG */
|