diff options
author | Henry Stiles <henry.stiles@artifex.com> | 1998-07-28 06:22:20 +0000 |
---|---|---|
committer | Henry Stiles <henry.stiles@artifex.com> | 1998-07-28 06:22:20 +0000 |
commit | 5fbdbaab7335a147a3a7890b5c6fc123926815db (patch) | |
tree | 154edc89b06c38333fd6d4b9abaf0ee8740ddf6a /gs/src/gxclbits.c | |
parent | 14cf10e3738f95f7864978c5a4778b50fb39524b (diff) |
This commit was generated by cvs2svn to compensate for changes in r257,
which included commits to RCS files with non-trunk default branches.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@258 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs/src/gxclbits.c')
-rw-r--r-- | gs/src/gxclbits.c | 1152 |
1 files changed, 574 insertions, 578 deletions
diff --git a/gs/src/gxclbits.c b/gs/src/gxclbits.c index c240b0591..a01fc5300 100644 --- a/gs/src/gxclbits.c +++ b/gs/src/gxclbits.c @@ -1,20 +1,20 @@ /* Copyright (C) 1995, 1996, 1997 Aladdin Enterprises. All rights reserved. - - This file is part of Aladdin Ghostscript. - - Aladdin 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 Ghostscript Free Public - License (the "License") for full details. - - Every copy of Aladdin 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 Aladdin 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. -*/ + + This file is part of Aladdin Ghostscript. + + Aladdin 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 Ghostscript Free Public + License (the "License") for full details. + + Every copy of Aladdin 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 Aladdin 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. + */ /* gxclbits.c */ /* Halftone and bitmap writing for command lists */ @@ -24,17 +24,17 @@ #include "gserrors.h" #include "gsbitops.h" #include "gxdevice.h" -#include "gxdevmem.h" /* must precede gxcldev.h */ +#include "gxdevmem.h" /* must precede gxcldev.h */ #include "gxcldev.h" #include "gxfmap.h" /* * Define when, if ever, to write character bitmaps in all bands. * Set this to: - * 0 to always write in all bands; - * N to write in all bands when the character has been seen in N+1 - * bands on a page; - * max_ushort to never write in all bands. + * 0 to always write in all bands; + * N to write in all bands when the character has been seen in N+1 + * bands on a page; + * max_ushort to never write in all bands. */ #define CHAR_ALL_BANDS_COUNT max_ushort @@ -48,22 +48,23 @@ */ uint clist_bitmap_bytes(uint width_bits, uint height, int compression_mask, - uint *width_bytes, uint *raster) -{ uint full_raster = *raster = bitmap_raster(width_bits); - uint short_raster = (width_bits + 7) >> 3; - uint width_bytes_last; - - if ( compression_mask & cmd_mask_compress_any ) - *width_bytes = width_bytes_last = full_raster; - else if ( short_raster <= cmd_max_short_width_bytes || - height <= 1 || - (compression_mask & decompress_spread) != 0 - ) - *width_bytes = width_bytes_last = short_raster; - else - *width_bytes = full_raster, width_bytes_last = short_raster; - return - (height == 0 ? 0 : *width_bytes * (height - 1) + width_bytes_last); + uint * width_bytes, uint * raster) +{ + uint full_raster = *raster = bitmap_raster(width_bits); + uint short_raster = (width_bits + 7) >> 3; + uint width_bytes_last; + + if (compression_mask & cmd_mask_compress_any) + *width_bytes = width_bytes_last = full_raster; + else if (short_raster <= cmd_max_short_width_bytes || + height <= 1 || + (compression_mask & decompress_spread) != 0 + ) + *width_bytes = width_bytes_last = short_raster; + else + *width_bytes = full_raster, width_bytes_last = short_raster; + return + (height == 0 ? 0 : *width_bytes * (height - 1) + width_bytes_last); } /* @@ -71,38 +72,37 @@ clist_bitmap_bytes(uint width_bits, uint height, int compression_mask, * necessary. We require height >= 1, raster >= bitmap_raster(width_bits). */ private int -cmd_compress_bitmap(stream_state *st, const byte *data, uint width_bits, - uint raster, uint height, stream_cursor_write *pw) -{ uint width_bytes = bitmap_raster(width_bits); - int status = 0; - stream_cursor_read r; - - r.ptr = data - 1; - if ( raster == width_bytes ) - { r.limit = r.ptr + raster * height; - status = (*st->template->process)(st, &r, pw, true); - } - else - { /* Compress row-by-row. */ - uint y; - for ( y = 1; (r.limit = r.ptr + width_bytes), y < height; ++y ) - { status = (*st->template->process)(st, &r, pw, false); - if ( status ) - break; - if ( r.ptr != r.limit ) - { /* We don't attempt to handle compressors that */ - /* require >1 input byte to make progress. */ - status = -1; - break; - } - r.ptr += raster - width_bytes; - } - if ( status == 0 ) - status = (*st->template->process)(st, &r, pw, true); - } - if ( st->template->release ) - (*st->template->release)(st); - return status; +cmd_compress_bitmap(stream_state * st, const byte * data, uint width_bits, + uint raster, uint height, stream_cursor_write * pw) +{ + uint width_bytes = bitmap_raster(width_bits); + int status = 0; + stream_cursor_read r; + + r.ptr = data - 1; + if (raster == width_bytes) { + r.limit = r.ptr + raster * height; + status = (*st->template->process) (st, &r, pw, true); + } else { /* Compress row-by-row. */ + uint y; + + for (y = 1; (r.limit = r.ptr + width_bytes), y < height; ++y) { + status = (*st->template->process) (st, &r, pw, false); + if (status) + break; + if (r.ptr != r.limit) { /* We don't attempt to handle compressors that */ + /* require >1 input byte to make progress. */ + status = -1; + break; + } + r.ptr += raster - width_bytes; + } + if (status == 0) + status = (*st->template->process) (st, &r, pw, true); + } + if (st->template->release) + (*st->template->release) (st); + return status; } /* @@ -115,165 +115,167 @@ cmd_compress_bitmap(stream_state *st, const byte *data, uint width_bits, * but doesn't fill them in. */ int -cmd_put_bits(gx_device_clist_writer *cldev, gx_clist_state *pcls, - const byte *data, uint width_bits, uint height, uint raster, int op_size, - int compression_mask, byte **pdp, uint *psize) -{ uint short_raster, full_raster; - uint short_size = - clist_bitmap_bytes(width_bits, height, - compression_mask & ~cmd_mask_compress_any, - &short_raster, &full_raster); - uint uncompressed_raster; - uint uncompressed_size = - clist_bitmap_bytes(width_bits, height, compression_mask, - &uncompressed_raster, &full_raster); - uint max_size = cbuf_size - op_size; - gs_memory_t *memory_allocator - = cldev->memory ? cldev->memory : &gs_memory_default; - byte *dp; - int compress = 0; +cmd_put_bits(gx_device_clist_writer * cldev, gx_clist_state * pcls, + const byte * data, uint width_bits, uint height, uint raster, int op_size, + int compression_mask, byte ** pdp, uint * psize) +{ + uint short_raster, full_raster; + uint short_size = + clist_bitmap_bytes(width_bits, height, + compression_mask & ~cmd_mask_compress_any, + &short_raster, &full_raster); + uint uncompressed_raster; + uint uncompressed_size = + clist_bitmap_bytes(width_bits, height, compression_mask, + &uncompressed_raster, &full_raster); + uint max_size = cbuf_size - op_size; + gs_memory_t *memory_allocator + = cldev->memory ? cldev->memory : &gs_memory_default; + byte *dp; + int compress = 0; + + /* + * See if compressing the bits is possible and worthwhile. + * Currently we can't compress if the compressed data won't fit in + * the command reading buffer, or if the decompressed data won't fit + * in the buffer and decompress_elsewhere isn't set. + */ + if (short_size >= 50 && + (compression_mask & cmd_mask_compress_any) != 0 && + (uncompressed_size <= max_size || + (compression_mask & decompress_elsewhere) != 0) + ) { + union ss_ { + stream_state ss; + stream_CFE_state cf; + stream_RLE_state rl; + } sstate; + + *psize = op_size + uncompressed_size; + if (pcls != 0) { + int code = set_cmd_put_op(dp, cldev, pcls, 0, *psize); + + if (code < 0) + return code; + } else { + int code = set_cmd_put_all_op(dp, cldev, 0, *psize); + if (code < 0) + return code; + } + cmd_uncount_op(0, *psize); /* - * See if compressing the bits is possible and worthwhile. - * Currently we can't compress if the compressed data won't fit in - * the command reading buffer, or if the decompressed data won't fit - * in the buffer and decompress_elsewhere isn't set. + * Note that we currently keep all the padding if we are + * compressing. This is ridiculous, but it's too hard to + * change right now. */ - if ( short_size >= 50 && - (compression_mask & cmd_mask_compress_any) != 0 && - (uncompressed_size <= max_size || - (compression_mask & decompress_elsewhere) != 0) - ) - { union ss_ { - stream_state ss; - stream_CFE_state cf; - stream_RLE_state rl; - } sstate; - - *psize = op_size + uncompressed_size; - if ( pcls != 0 ) - { int code = set_cmd_put_op(dp, cldev, pcls, 0, *psize); - if (code < 0) - return code; - } - else - { int code = set_cmd_put_all_op(dp, cldev, 0, *psize); - if (code < 0) - return code; - } - cmd_uncount_op(0, *psize); - /* - * Note that we currently keep all the padding if we are - * compressing. This is ridiculous, but it's too hard to - * change right now. - */ - if ( compression_mask & (1 << cmd_compress_cfe) ) - { /* Try CCITTFax compression. */ - clist_cfe_init(&sstate.cf, - uncompressed_raster << 3 /*width_bits*/, memory_allocator); - sstate.ss.template = &s_CFE_template; - compress = cmd_compress_cfe; - } - else if ( compression_mask & (1 << cmd_compress_rle) ) - { /* Try RLE compression. */ - clist_rle_init(&sstate.rl); - sstate.ss.template = &s_RLE_template; - compress = cmd_compress_rle; - } - if ( compress ) - { byte *wbase = dp + (op_size - 1); - stream_cursor_write w; - /* - * We can give up on compressing if we generate too much - * output to fit in the command reading buffer, or too - * much to make compression worthwhile. - */ - uint wmax = min(uncompressed_size, max_size); - int status; - - w.ptr = wbase; - w.limit = w.ptr + min(wmax, short_size >> 1); - status = cmd_compress_bitmap((stream_state *)&sstate, data, - uncompressed_raster << 3 /*width_bits*/, - raster, height, &w); - if ( status == 0 ) - { /* Use compressed representation. */ - uint wcount = w.ptr - wbase; - cmd_shorten_list_op(cldev, - (pcls ? &pcls->list : &cldev->band_range_list), - uncompressed_size - wcount); - *psize = op_size + wcount; - goto out; - } - } - if ( uncompressed_size > max_size ) - { cmd_shorten_list_op(cldev, - (pcls ? &pcls->list : &cldev->band_range_list), + if (compression_mask & (1 << cmd_compress_cfe)) { /* Try CCITTFax compression. */ + clist_cfe_init(&sstate.cf, + uncompressed_raster << 3 /*width_bits */ , memory_allocator); + sstate.ss.template = &s_CFE_template; + compress = cmd_compress_cfe; + } else if (compression_mask & (1 << cmd_compress_rle)) { /* Try RLE compression. */ + clist_rle_init(&sstate.rl); + sstate.ss.template = &s_RLE_template; + compress = cmd_compress_rle; + } + if (compress) { + byte *wbase = dp + (op_size - 1); + stream_cursor_write w; + + /* + * We can give up on compressing if we generate too much + * output to fit in the command reading buffer, or too + * much to make compression worthwhile. + */ + uint wmax = min(uncompressed_size, max_size); + int status; + + w.ptr = wbase; + w.limit = w.ptr + min(wmax, short_size >> 1); + status = cmd_compress_bitmap((stream_state *) & sstate, data, + uncompressed_raster << 3 /*width_bits */ , + raster, height, &w); + if (status == 0) { /* Use compressed representation. */ + uint wcount = w.ptr - wbase; + + cmd_shorten_list_op(cldev, + (pcls ? &pcls->list : &cldev->band_range_list), + uncompressed_size - wcount); + *psize = op_size + wcount; + goto out; + } + } + if (uncompressed_size > max_size) { + cmd_shorten_list_op(cldev, + (pcls ? &pcls->list : &cldev->band_range_list), *psize); - return_error(gs_error_limitcheck); - } - if ( uncompressed_size != short_size ) - { cmd_shorten_list_op(cldev, - (pcls ? &pcls->list : &cldev->band_range_list), + return_error(gs_error_limitcheck); + } + if (uncompressed_size != short_size) { + cmd_shorten_list_op(cldev, + (pcls ? &pcls->list : &cldev->band_range_list), uncompressed_size - short_size); - *psize = op_size + short_size; - } - compress = 0; - } - else if ( uncompressed_size > max_size ) - return_error(gs_error_limitcheck); - else - { *psize = op_size + short_size; - if ( pcls != 0 ) - { int code = set_cmd_put_op(dp, cldev, pcls, 0, *psize); - if (code < 0) - return code; - } - else - { int code = set_cmd_put_all_op(dp, cldev, 0, *psize); - if (code < 0) - return code; - } - cmd_uncount_op(0, *psize); - } - bytes_copy_rectangle(dp + op_size, short_raster, data, raster, - short_raster, height); -out: *pdp = dp; - return compress; + *psize = op_size + short_size; + } + compress = 0; + } else if (uncompressed_size > max_size) + return_error(gs_error_limitcheck); + else { + *psize = op_size + short_size; + if (pcls != 0) { + int code = set_cmd_put_op(dp, cldev, pcls, 0, *psize); + + if (code < 0) + return code; + } else { + int code = set_cmd_put_all_op(dp, cldev, 0, *psize); + + if (code < 0) + return code; + } + cmd_uncount_op(0, *psize); + } + bytes_copy_rectangle(dp + op_size, short_raster, data, raster, + short_raster, height); + out:*pdp = dp; + return compress; } /* Add a command to set the tile size and depth. */ private uint -cmd_size_tile_params(const gx_strip_bitmap *tile) -{ return 2 + cmd_size_w(tile->rep_width) + cmd_size_w(tile->rep_height) + - (tile->rep_width == tile->size.x ? 0 : - cmd_size_w(tile->size.x / tile->rep_width)) + - (tile->rep_height == tile->size.y ? 0 : - cmd_size_w(tile->size.y / tile->rep_height)) + - (tile->rep_shift == 0 ? 0 : cmd_size_w(tile->rep_shift)); +cmd_size_tile_params(const gx_strip_bitmap * tile) +{ + return 2 + cmd_size_w(tile->rep_width) + cmd_size_w(tile->rep_height) + + (tile->rep_width == tile->size.x ? 0 : + cmd_size_w(tile->size.x / tile->rep_width)) + + (tile->rep_height == tile->size.y ? 0 : + cmd_size_w(tile->size.y / tile->rep_height)) + + (tile->rep_shift == 0 ? 0 : cmd_size_w(tile->rep_shift)); } private void -cmd_store_tile_params(byte *dp, const gx_strip_bitmap *tile, int depth, - uint csize) -{ byte *p = dp + 2; - byte bd = depth - 1; - - *dp = cmd_count_op(cmd_opv_set_tile_size, csize); - p = cmd_put_w(tile->rep_width, p); - p = cmd_put_w(tile->rep_height, p); - if ( tile->rep_width != tile->size.x ) { - p = cmd_put_w(tile->size.x / tile->rep_width, p); - bd |= 0x20; - } - if ( tile->rep_height != tile->size.y ) { - p = cmd_put_w(tile->size.y / tile->rep_height, p); - bd |= 0x40; - } - if ( tile->rep_shift != 0 ) { - cmd_put_w(tile->rep_shift, p); - bd |= 0x80; - } - dp[1] = bd; +cmd_store_tile_params(byte * dp, const gx_strip_bitmap * tile, int depth, + uint csize) +{ + byte *p = dp + 2; + byte bd = depth - 1; + + *dp = cmd_count_op(cmd_opv_set_tile_size, csize); + p = cmd_put_w(tile->rep_width, p); + p = cmd_put_w(tile->rep_height, p); + if (tile->rep_width != tile->size.x) { + p = cmd_put_w(tile->size.x / tile->rep_width, p); + bd |= 0x20; + } + if (tile->rep_height != tile->size.y) { + p = cmd_put_w(tile->size.y / tile->rep_height, p); + bd |= 0x40; + } + if (tile->rep_shift != 0) { + cmd_put_w(tile->rep_shift, p); + bd |= 0x80; + } + dp[1] = bd; } /* Add a command to set the tile index. */ @@ -302,34 +304,34 @@ cmd_store_tile_params(byte *dp, const gx_strip_bitmap *tile, int depth, /* If necessary, write out data for a single color map. */ int -cmd_put_color_map(gx_device_clist_writer *cldev, cmd_map_index map_index, - const gx_transfer_map *map, gs_id *pid) -{ byte *dp; - int code; - - if ( map == 0 ) - { if ( pid && *pid == gs_no_id ) - return 0; /* no need to write */ - code = set_cmd_put_all_op(dp, cldev, cmd_opv_set_misc, 2); - if (code < 0) - return code; - dp[1] = cmd_set_misc_map + map_index; - if ( pid ) - *pid = gs_no_id; - } - else - { if ( pid && map->id == *pid ) - return 0; /* no need to write */ - code = set_cmd_put_all_op(dp, cldev, cmd_opv_set_misc, - 2 + sizeof(map->values)); - if (code < 0) - return code; - dp[1] = cmd_set_misc_map + 0x20 + map_index; - memcpy(dp + 2, map->values, sizeof(map->values)); - if ( pid ) - *pid = map->id; - } - return 0; +cmd_put_color_map(gx_device_clist_writer * cldev, cmd_map_index map_index, + const gx_transfer_map * map, gs_id * pid) +{ + byte *dp; + int code; + + if (map == 0) { + if (pid && *pid == gs_no_id) + return 0; /* no need to write */ + code = set_cmd_put_all_op(dp, cldev, cmd_opv_set_misc, 2); + if (code < 0) + return code; + dp[1] = cmd_set_misc_map + map_index; + if (pid) + *pid = gs_no_id; + } else { + if (pid && map->id == *pid) + return 0; /* no need to write */ + code = set_cmd_put_all_op(dp, cldev, cmd_opv_set_misc, + 2 + sizeof(map->values)); + if (code < 0) + return code; + dp[1] = cmd_set_misc_map + 0x20 + map_index; + memcpy(dp + 2, map->values, sizeof(map->values)); + if (pid) + *pid = map->id; + } + return 0; } /* ------ Tile cache management ------ */ @@ -339,145 +341,147 @@ cmd_put_color_map(gx_device_clist_writer *cldev, cmd_map_index map_index, #define tile_id_hash(id) (id) #define tile_hash_next(index) ((index) + 413) /* arbitrary large odd # */ typedef struct tile_loc_s { - uint index; - tile_slot *tile; + uint index; + tile_slot *tile; } tile_loc; /* Look up a tile or character in the cache. If found, set the index and */ /* pointer; if not, set the index to the insertion point. */ private bool -clist_find_bits(gx_device_clist_writer *cldev, gx_bitmap_id id, tile_loc *ploc) -{ uint index = tile_id_hash(id); - const tile_hash *table = cldev->tile_table; - uint mask = cldev->tile_hash_mask; - ulong offset; - - for ( ; (offset = table[index &= mask].offset) != 0; - index = tile_hash_next(index) - ) - { tile_slot *tile = (tile_slot *)(cldev->data + offset); - if ( tile->id == id ) - { ploc->index = index; - ploc->tile = tile; - return true; - } - } - ploc->index = index; - return false; +clist_find_bits(gx_device_clist_writer * cldev, gx_bitmap_id id, tile_loc * ploc) +{ + uint index = tile_id_hash(id); + const tile_hash *table = cldev->tile_table; + uint mask = cldev->tile_hash_mask; + ulong offset; + + for (; (offset = table[index &= mask].offset) != 0; + index = tile_hash_next(index) + ) { + tile_slot *tile = (tile_slot *) (cldev->data + offset); + + if (tile->id == id) { + ploc->index = index; + ploc->tile = tile; + return true; + } + } + ploc->index = index; + return false; } /* Delete a tile from the cache. */ private void -clist_delete_tile(gx_device_clist_writer *cldev, tile_slot *slot) -{ tile_hash *table = cldev->tile_table; - uint mask = cldev->tile_hash_mask; - uint index = slot->index; - ulong offset; - - if_debug2('L', "[L]deleting index=%u, offset=%lu\n", - index, (ulong)((byte *)slot - cldev->data)); - gx_bits_cache_free(&cldev->bits, (gx_cached_bits_head *)slot, - &cldev->chunk); - table[index].offset = 0; - /* Delete the entry from the hash table. */ - /* We'd like to move up any later entries, so that we don't need */ - /* a deleted mark, but it's too difficult to note this in the */ - /* band list, so instead, we just delete any entries that */ - /* would need to be moved. */ - while ( (offset = table[index = tile_hash_next(index) & mask].offset) != 0 ) - { tile_slot *tile = (tile_slot *)(cldev->data + offset); - tile_loc loc; - if ( !clist_find_bits(cldev, tile->id, &loc) ) - { /* We didn't find it, so it should be moved into a slot */ - /* that we just vacated; instead, delete it. */ - if_debug2('L', "[L]move-deleting index=%u, offset=%lu\n", - index, offset); - gx_bits_cache_free(&cldev->bits, - (gx_cached_bits_head *)(cldev->data + offset), - &cldev->chunk); - table[index].offset = 0; - } - } +clist_delete_tile(gx_device_clist_writer * cldev, tile_slot * slot) +{ + tile_hash *table = cldev->tile_table; + uint mask = cldev->tile_hash_mask; + uint index = slot->index; + ulong offset; + + if_debug2('L', "[L]deleting index=%u, offset=%lu\n", + index, (ulong) ((byte *) slot - cldev->data)); + gx_bits_cache_free(&cldev->bits, (gx_cached_bits_head *) slot, + &cldev->chunk); + table[index].offset = 0; + /* Delete the entry from the hash table. */ + /* We'd like to move up any later entries, so that we don't need */ + /* a deleted mark, but it's too difficult to note this in the */ + /* band list, so instead, we just delete any entries that */ + /* would need to be moved. */ + while ((offset = table[index = tile_hash_next(index) & mask].offset) != 0) { + tile_slot *tile = (tile_slot *) (cldev->data + offset); + tile_loc loc; + + if (!clist_find_bits(cldev, tile->id, &loc)) { /* We didn't find it, so it should be moved into a slot */ + /* that we just vacated; instead, delete it. */ + if_debug2('L', "[L]move-deleting index=%u, offset=%lu\n", + index, offset); + gx_bits_cache_free(&cldev->bits, + (gx_cached_bits_head *) (cldev->data + offset), + &cldev->chunk); + table[index].offset = 0; + } + } } /* Add a tile to the cache. */ /* tile->raster holds the raster for the replicated tile; */ /* we pass the raster of the actual data separately. */ private int -clist_add_tile(gx_device_clist_writer *cldev, const gx_strip_bitmap *tiles, - uint sraster, int depth) -{ uint raster = tiles->raster; - uint size_bytes = raster * tiles->size.y; - uint tsize = - sizeof(tile_slot) + cldev->tile_band_mask_size + size_bytes; - gx_cached_bits_head *slot_head; +clist_add_tile(gx_device_clist_writer * cldev, const gx_strip_bitmap * tiles, + uint sraster, int depth) +{ + uint raster = tiles->raster; + uint size_bytes = raster * tiles->size.y; + uint tsize = + sizeof(tile_slot) + cldev->tile_band_mask_size + size_bytes; + gx_cached_bits_head *slot_head; + #define slot ((tile_slot *)slot_head) - if ( cldev->bits.csize == cldev->tile_max_count ) - { /* Don't let the hash table get too full: delete an entry. */ - /* Since gx_bits_cache_alloc returns an entry to delete when */ - /* it fails, just force it to fail. */ - gx_bits_cache_alloc(&cldev->bits, (ulong)cldev->chunk.size, + if (cldev->bits.csize == cldev->tile_max_count) { /* Don't let the hash table get too full: delete an entry. */ + /* Since gx_bits_cache_alloc returns an entry to delete when */ + /* it fails, just force it to fail. */ + gx_bits_cache_alloc(&cldev->bits, (ulong) cldev->chunk.size, + &slot_head); + if (slot_head == 0) { /* Wrap around and retry. */ + cldev->bits.cnext = 0; + gx_bits_cache_alloc(&cldev->bits, (ulong) cldev->chunk.size, &slot_head); - if ( slot_head == 0 ) - { /* Wrap around and retry. */ - cldev->bits.cnext = 0; - gx_bits_cache_alloc(&cldev->bits, (ulong)cldev->chunk.size, - &slot_head); #ifdef DEBUG - if ( slot_head == 0 ) - { lprintf("No entry to delete!\n"); - return_error(gs_error_Fatal); - } + if (slot_head == 0) { + lprintf("No entry to delete!\n"); + return_error(gs_error_Fatal); + } #endif - } + } + clist_delete_tile(cldev, slot); + } + /* Allocate the space for the new entry, deleting entries as needed. */ + while (gx_bits_cache_alloc(&cldev->bits, (ulong) tsize, &slot_head) < 0) { + if (slot_head == 0) { /* Wrap around. */ + if (cldev->bits.cnext == 0) { /* Too big to fit. We should probably detect this */ + /* sooner, since if we get here, we've cleared the */ + /* cache. */ + return_error(gs_error_limitcheck); + } + cldev->bits.cnext = 0; + } else clist_delete_tile(cldev, slot); - } - /* Allocate the space for the new entry, deleting entries as needed. */ - while ( gx_bits_cache_alloc(&cldev->bits, (ulong)tsize, &slot_head) < 0 ) - { if ( slot_head == 0 ) - { /* Wrap around. */ - if ( cldev->bits.cnext == 0 ) - { /* Too big to fit. We should probably detect this */ - /* sooner, since if we get here, we've cleared the */ - /* cache. */ - return_error(gs_error_limitcheck); - } - cldev->bits.cnext = 0; - } - else - clist_delete_tile(cldev, slot); - } - /* Fill in the entry. */ - slot->cb_depth = depth; - slot->cb_raster = raster; - slot->width = tiles->rep_width; - slot->height = tiles->rep_height; - slot->shift = slot->rep_shift = tiles->rep_shift; - slot->x_reps = slot->y_reps = 1; - slot->id = tiles->id; - memset(ts_mask(slot), 0, cldev->tile_band_mask_size); - bytes_copy_rectangle(ts_bits(cldev, slot), raster, - tiles->data, sraster, - (tiles->rep_width * depth + 7) >> 3, - tiles->rep_height); - /* Make the hash table entry. */ - { tile_loc loc; + } + /* Fill in the entry. */ + slot->cb_depth = depth; + slot->cb_raster = raster; + slot->width = tiles->rep_width; + slot->height = tiles->rep_height; + slot->shift = slot->rep_shift = tiles->rep_shift; + slot->x_reps = slot->y_reps = 1; + slot->id = tiles->id; + memset(ts_mask(slot), 0, cldev->tile_band_mask_size); + bytes_copy_rectangle(ts_bits(cldev, slot), raster, + tiles->data, sraster, + (tiles->rep_width * depth + 7) >> 3, + tiles->rep_height); + /* Make the hash table entry. */ + { + tile_loc loc; + #ifdef DEBUG - if ( clist_find_bits(cldev, tiles->id, &loc) ) + if (clist_find_bits(cldev, tiles->id, &loc)) lprintf1("clist_find_bits(0x%lx) should have failed!\n", - (ulong)tiles->id); + (ulong) tiles->id); #else - clist_find_bits(cldev, tiles->id, &loc); /* always fails */ + clist_find_bits(cldev, tiles->id, &loc); /* always fails */ #endif - slot->index = loc.index; - cldev->tile_table[loc.index].offset = - (byte *)slot_head - cldev->data; - if_debug2('L', "[L]adding index=%u, offset=%lu\n", - loc.index, cldev->tile_table[loc.index].offset); - } - slot->num_bands = 0; - return 0; + slot->index = loc.index; + cldev->tile_table[loc.index].offset = + (byte *) slot_head - cldev->data; + if_debug2('L', "[L]adding index=%u, offset=%lu\n", + loc.index, cldev->tile_table[loc.index].offset); + } + slot->num_bands = 0; + return 0; } /* ------ Driver procedure support ------ */ @@ -485,51 +489,52 @@ clist_add_tile(gx_device_clist_writer *cldev, const gx_strip_bitmap *tiles, /* Change the tile parameters (size and depth). */ /* Currently we do this for all bands at once. */ private void -clist_new_tile_params(gx_strip_bitmap *new_tile, const gx_strip_bitmap *tiles, - int depth, const gx_device_clist_writer *cldev) -{ /* - * Adjust the replication factors. If we can, we replicate - * the tile in X up to 32 bytes, and then in Y up to 4 copies, - * as long as we don't exceed a total tile size of 256 bytes, - * or more than 255 repetitions in X or Y, or make the tile so - * large that not all possible tiles will fit in the cache. - * Also, don't attempt Y replication if shifting is required. - */ +clist_new_tile_params(gx_strip_bitmap * new_tile, const gx_strip_bitmap * tiles, + int depth, const gx_device_clist_writer * cldev) +{ /* + * Adjust the replication factors. If we can, we replicate + * the tile in X up to 32 bytes, and then in Y up to 4 copies, + * as long as we don't exceed a total tile size of 256 bytes, + * or more than 255 repetitions in X or Y, or make the tile so + * large that not all possible tiles will fit in the cache. + * Also, don't attempt Y replication if shifting is required. + */ #define max_tile_reps_x 255 #define max_tile_bytes_x 32 #define max_tile_reps_y 4 #define max_tile_bytes 256 - uint rep_width = tiles->rep_width; - uint rep_height = tiles->rep_height; - uint rep_width_bits = rep_width * depth; - uint tile_overhead = - sizeof(tile_slot) + cldev->tile_band_mask_size; - uint max_bytes = cldev->chunk.size / (rep_width_bits * rep_height); - - max_bytes -= min(max_bytes, tile_overhead); - if ( max_bytes > max_tile_bytes ) - max_bytes = max_tile_bytes; - *new_tile = *tiles; - { uint max_bits_x = max_bytes * 8 / rep_height; - uint reps_x = - min(max_bits_x, max_tile_bytes_x * 8) / rep_width_bits; - uint reps_y; - - while ( reps_x > max_tile_reps_x ) + uint rep_width = tiles->rep_width; + uint rep_height = tiles->rep_height; + uint rep_width_bits = rep_width * depth; + uint tile_overhead = + sizeof(tile_slot) + cldev->tile_band_mask_size; + uint max_bytes = cldev->chunk.size / (rep_width_bits * rep_height); + + max_bytes -= min(max_bytes, tile_overhead); + if (max_bytes > max_tile_bytes) + max_bytes = max_tile_bytes; + *new_tile = *tiles; + { + uint max_bits_x = max_bytes * 8 / rep_height; + uint reps_x = + min(max_bits_x, max_tile_bytes_x * 8) / rep_width_bits; + uint reps_y; + + while (reps_x > max_tile_reps_x) reps_x >>= 1; - new_tile->size.x = max(reps_x, 1) * rep_width; - new_tile->raster = bitmap_raster(new_tile->size.x * depth); - if ( tiles->shift != 0 ) + new_tile->size.x = max(reps_x, 1) * rep_width; + new_tile->raster = bitmap_raster(new_tile->size.x * depth); + if (tiles->shift != 0) reps_y = 1; - else - { reps_y = max_bytes / (new_tile->raster * rep_height); - if ( reps_y > max_tile_reps_y ) + else { + reps_y = max_bytes / (new_tile->raster * rep_height); + if (reps_y > max_tile_reps_y) reps_y = max_tile_reps_y; - else if ( reps_y < 1 ) + else if (reps_y < 1) reps_y = 1; - } - new_tile->size.y = reps_y * rep_height; } + new_tile->size.y = reps_y * rep_height; + } #undef max_tile_reps_x #undef max_tile_bytes_x #undef max_tile_reps_y @@ -538,10 +543,11 @@ clist_new_tile_params(gx_strip_bitmap *new_tile, const gx_strip_bitmap *tiles, /* Change tile for clist_tile_rectangle. */ int -clist_change_tile(gx_device_clist_writer *cldev, gx_clist_state *pcls, - const gx_strip_bitmap *tiles, int depth) -{ tile_loc loc; - int code; +clist_change_tile(gx_device_clist_writer * cldev, gx_clist_state * pcls, + const gx_strip_bitmap * tiles, int depth) +{ + tile_loc loc; + int code; #define tile_params_differ(cldev, tiles, depth)\ ((tiles)->rep_width != (cldev)->tile_params.rep_width ||\ @@ -549,194 +555,184 @@ clist_change_tile(gx_device_clist_writer *cldev, gx_clist_state *pcls, (tiles)->rep_shift != (cldev)->tile_params.rep_shift ||\ (depth) != (cldev)->tile_depth) -top: if ( clist_find_bits(cldev, tiles->id, &loc) ) - { /* The bitmap is in the cache. Check whether this band */ - /* knows about it. */ - int band_index = pcls - cldev->states; - byte *bptr = ts_mask(loc.tile) + (band_index >> 3); - byte bmask = 1 << (band_index & 7); - - if ( *bptr & bmask ) - { /* Already known. Just set the index. */ - if ( pcls->tile_index == loc.index ) - return 0; - cmd_put_tile_index_inline(cldev, pcls, loc.index); - } - else - { uint extra = 0; - if tile_params_differ(cldev, tiles, depth) - { /* - * We have a cached tile whose parameters differ from - * the current ones. Because of the way tile IDs are - * managed, this is currently only possible when mixing - * Patterns and halftones, but if we didn't generate new - * IDs each time the main halftone cache needed to be - * refreshed, this could also happen simply from - * switching screens. - */ - int band; - - clist_new_tile_params(&cldev->tile_params, tiles, depth, - cldev); - cldev->tile_depth = depth; - /* No band knows about the new parameters. */ - for ( band = cldev->tile_known_min; - band <= cldev->tile_known_max; - ++band - ) - cldev->states[band].known &= ~tile_params_known; - cldev->tile_known_min = cldev->nbands; - cldev->tile_known_max = -1; - } - if ( !(pcls->known & tile_params_known) ) - { /* We're going to have to write the tile parameters. */ - extra = cmd_size_tile_params(&cldev->tile_params); - } - { /* - * This band doesn't know this tile yet, so output the - * bits. Note that the offset we write is the one used by - * the reading phase, not the writing phase. Note also - * that the size of the cached and written tile may differ - * from that of the client's tile. Finally, note that - * this tile's size parameters are guaranteed to be - * compatible with those stored in the device - * (cldev->tile_params). - */ - ulong offset = (byte *)loc.tile - cldev->chunk.data; - uint rsize = - extra + 1 + cmd_size_w(loc.index) + cmd_size_w(offset); - byte *dp; - uint csize; - uint compress; - int code = - cmd_put_bits(cldev, pcls, ts_bits(cldev, loc.tile), - tiles->rep_width * depth, tiles->rep_height, - loc.tile->cb_raster, rsize, - (cldev->tile_params.size.x > tiles->rep_width ? - decompress_elsewhere | decompress_spread : - decompress_elsewhere), - &dp, &csize); - - if ( code < 0 ) + top:if (clist_find_bits(cldev, tiles->id, &loc)) { /* The bitmap is in the cache. Check whether this band */ + /* knows about it. */ + int band_index = pcls - cldev->states; + byte *bptr = ts_mask(loc.tile) + (band_index >> 3); + byte bmask = 1 << (band_index & 7); + + if (*bptr & bmask) { /* Already known. Just set the index. */ + if (pcls->tile_index == loc.index) + return 0; + cmd_put_tile_index_inline(cldev, pcls, loc.index); + } else { + uint extra = 0; + + if tile_params_differ + (cldev, tiles, depth) { /* + * We have a cached tile whose parameters differ from + * the current ones. Because of the way tile IDs are + * managed, this is currently only possible when mixing + * Patterns and halftones, but if we didn't generate new + * IDs each time the main halftone cache needed to be + * refreshed, this could also happen simply from + * switching screens. + */ + int band; + + clist_new_tile_params(&cldev->tile_params, tiles, depth, + cldev); + cldev->tile_depth = depth; + /* No band knows about the new parameters. */ + for (band = cldev->tile_known_min; + band <= cldev->tile_known_max; + ++band + ) + cldev->states[band].known &= ~tile_params_known; + cldev->tile_known_min = cldev->nbands; + cldev->tile_known_max = -1; + } + if (!(pcls->known & tile_params_known)) { /* We're going to have to write the tile parameters. */ + extra = cmd_size_tile_params(&cldev->tile_params); + } { /* + * This band doesn't know this tile yet, so output the + * bits. Note that the offset we write is the one used by + * the reading phase, not the writing phase. Note also + * that the size of the cached and written tile may differ + * from that of the client's tile. Finally, note that + * this tile's size parameters are guaranteed to be + * compatible with those stored in the device + * (cldev->tile_params). + */ + ulong offset = (byte *) loc.tile - cldev->chunk.data; + uint rsize = + extra + 1 + cmd_size_w(loc.index) + cmd_size_w(offset); + byte *dp; + uint csize; + uint compress; + int code = + cmd_put_bits(cldev, pcls, ts_bits(cldev, loc.tile), + tiles->rep_width * depth, tiles->rep_height, + loc.tile->cb_raster, rsize, + (cldev->tile_params.size.x > tiles->rep_width ? + decompress_elsewhere | decompress_spread : + decompress_elsewhere), + &dp, &csize); + + if (code < 0) return code; - compress = (uint)code; - if ( extra ) - { /* Write the tile parameters before writing the bits. */ - cmd_store_tile_params(dp, &cldev->tile_params, depth, - extra); - dp += extra; - /* This band now knows the parameters. */ - pcls->known |= tile_params_known; - if ( band_index < cldev->tile_known_min ) + compress = (uint) code; + if (extra) { /* Write the tile parameters before writing the bits. */ + cmd_store_tile_params(dp, &cldev->tile_params, depth, + extra); + dp += extra; + /* This band now knows the parameters. */ + pcls->known |= tile_params_known; + if (band_index < cldev->tile_known_min) cldev->tile_known_min = band_index; - if ( band_index > cldev->tile_known_max ) + if (band_index > cldev->tile_known_max) cldev->tile_known_max = band_index; - } - *dp = cmd_count_op(cmd_opv_set_tile_bits, csize - extra); - dp++; - dp = cmd_put_w(loc.index, dp); - cmd_put_w(offset, dp); - *bptr |= bmask; - loc.tile->num_bands++; } - } - pcls->tile_index = loc.index; - pcls->tile_id = loc.tile->id; - return 0; - } - /* The tile is not in the cache, add it. */ - { gx_strip_bitmap new_tile; - gx_strip_bitmap *ptile; - - /* Ensure that the tile size is compatible. */ - if ( tile_params_differ(cldev, tiles, depth) ) - { /* We'll reset cldev->tile_params when we write the bits. */ - clist_new_tile_params(&new_tile, tiles, depth, cldev); - ptile = &new_tile; - } - else - { cldev->tile_params.id = tiles->id; - cldev->tile_params.data = tiles->data; - ptile = &cldev->tile_params; + *dp = cmd_count_op(cmd_opv_set_tile_bits, csize - extra); + dp++; + dp = cmd_put_w(loc.index, dp); + cmd_put_w(offset, dp); + *bptr |= bmask; + loc.tile->num_bands++; } - code = clist_add_tile(cldev, ptile, tiles->raster, depth); - if ( code < 0 ) - return code; } - goto top; + pcls->tile_index = loc.index; + pcls->tile_id = loc.tile->id; + return 0; + } + /* The tile is not in the cache, add it. */ + { + gx_strip_bitmap new_tile; + gx_strip_bitmap *ptile; + + /* Ensure that the tile size is compatible. */ + if (tile_params_differ(cldev, tiles, depth)) { /* We'll reset cldev->tile_params when we write the bits. */ + clist_new_tile_params(&new_tile, tiles, depth, cldev); + ptile = &new_tile; + } else { + cldev->tile_params.id = tiles->id; + cldev->tile_params.data = tiles->data; + ptile = &cldev->tile_params; + } + code = clist_add_tile(cldev, ptile, tiles->raster, depth); + if (code < 0) + return code; + } + goto top; #undef tile_params_differ } /* Change "tile" for clist_copy_*. tiles->[rep_]shift must be zero. */ int -clist_change_bits(gx_device_clist_writer *cldev, gx_clist_state *pcls, - const gx_strip_bitmap *tiles, int depth) -{ tile_loc loc; - int code; - -top: if ( clist_find_bits(cldev, tiles->id, &loc) ) - { /* The bitmap is in the cache. Check whether this band */ - /* knows about it. */ - uint band_index = pcls - cldev->states; - byte *bptr = ts_mask(loc.tile) + (band_index >> 3); - byte bmask = 1 << (band_index & 7); - - if ( *bptr & bmask ) - { /* Already known. Just set the index. */ - if ( pcls->tile_index == loc.index ) - return 0; - cmd_put_tile_index_inline(cldev, pcls, loc.index); - } - else - { /* Not known yet. Output the bits. */ - /* Note that the offset we write is the one used by */ - /* the reading phase, not the writing phase. */ - ulong offset = (byte *)loc.tile - cldev->chunk.data; - uint rsize = 2 + cmd_size_w(loc.tile->width) + - cmd_size_w(loc.tile->height) + cmd_size_w(loc.index) + - cmd_size_w(offset); - byte *dp; - uint csize; - uint compress; - gx_clist_state *bit_pcls = pcls; - int code; - - if ( loc.tile->num_bands == CHAR_ALL_BANDS_COUNT ) - bit_pcls = NULL; - code = cmd_put_bits(cldev, bit_pcls, ts_bits(cldev, loc.tile), - loc.tile->width * depth, - loc.tile->height, loc.tile->cb_raster, - rsize, - (1 << cmd_compress_cfe) | decompress_elsewhere, - &dp, &csize); - - if ( code < 0 ) - return code; - compress = (uint)code; - *dp = cmd_count_op(cmd_opv_set_bits, csize); - dp[1] = (depth << 2) + compress; - dp += 2; - dp = cmd_put_w(loc.tile->width, dp); - dp = cmd_put_w(loc.tile->height, dp); - dp = cmd_put_w(loc.index, dp); - cmd_put_w(offset, dp); - if ( bit_pcls == NULL ) - { memset(ts_mask(loc.tile), 0xff, - cldev->tile_band_mask_size); - loc.tile->num_bands = cldev->nbands; - } - else - { *bptr |= bmask; - loc.tile->num_bands++; - } - } - pcls->tile_index = loc.index; - pcls->tile_id = loc.tile->id; - return 0; - } - /* The tile is not in the cache. */ - code = clist_add_tile(cldev, tiles, tiles->raster, depth); - if ( code < 0 ) - return code; - goto top; +clist_change_bits(gx_device_clist_writer * cldev, gx_clist_state * pcls, + const gx_strip_bitmap * tiles, int depth) +{ + tile_loc loc; + int code; + + top:if (clist_find_bits(cldev, tiles->id, &loc)) { /* The bitmap is in the cache. Check whether this band */ + /* knows about it. */ + uint band_index = pcls - cldev->states; + byte *bptr = ts_mask(loc.tile) + (band_index >> 3); + byte bmask = 1 << (band_index & 7); + + if (*bptr & bmask) { /* Already known. Just set the index. */ + if (pcls->tile_index == loc.index) + return 0; + cmd_put_tile_index_inline(cldev, pcls, loc.index); + } else { /* Not known yet. Output the bits. */ + /* Note that the offset we write is the one used by */ + /* the reading phase, not the writing phase. */ + ulong offset = (byte *) loc.tile - cldev->chunk.data; + uint rsize = 2 + cmd_size_w(loc.tile->width) + + cmd_size_w(loc.tile->height) + cmd_size_w(loc.index) + + cmd_size_w(offset); + byte *dp; + uint csize; + uint compress; + gx_clist_state *bit_pcls = pcls; + int code; + + if (loc.tile->num_bands == CHAR_ALL_BANDS_COUNT) + bit_pcls = NULL; + code = cmd_put_bits(cldev, bit_pcls, ts_bits(cldev, loc.tile), + loc.tile->width * depth, + loc.tile->height, loc.tile->cb_raster, + rsize, + (1 << cmd_compress_cfe) | decompress_elsewhere, + &dp, &csize); + + if (code < 0) + return code; + compress = (uint) code; + *dp = cmd_count_op(cmd_opv_set_bits, csize); + dp[1] = (depth << 2) + compress; + dp += 2; + dp = cmd_put_w(loc.tile->width, dp); + dp = cmd_put_w(loc.tile->height, dp); + dp = cmd_put_w(loc.index, dp); + cmd_put_w(offset, dp); + if (bit_pcls == NULL) { + memset(ts_mask(loc.tile), 0xff, + cldev->tile_band_mask_size); + loc.tile->num_bands = cldev->nbands; + } else { + *bptr |= bmask; + loc.tile->num_bands++; + } + } + pcls->tile_index = loc.index; + pcls->tile_id = loc.tile->id; + return 0; + } + /* The tile is not in the cache. */ + code = clist_add_tile(cldev, tiles, tiles->raster, depth); + if (code < 0) + return code; + goto top; } |