diff options
author | Henry Stiles <henry.stiles@artifex.com> | 1998-08-22 21:21:36 +0000 |
---|---|---|
committer | Henry Stiles <henry.stiles@artifex.com> | 1998-08-22 21:21:36 +0000 |
commit | 2e4f92ba231ce324c47f3c924585cc8c8cff229b (patch) | |
tree | e271d988b100be6fb354b6880cb018c6b5be11bf /gs/src/gxclrast.c | |
parent | 8ef783ae15b486e9a5ee9c846a21f4f89f925b1e (diff) | |
download | ghostpdl-2e4f92ba231ce324c47f3c924585cc8c8cff229b.tar.gz |
filters out the id string.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@321 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs/src/gxclrast.c')
-rw-r--r-- | gs/src/gxclrast.c | 1198 |
1 files changed, 644 insertions, 554 deletions
diff --git a/gs/src/gxclrast.c b/gs/src/gxclrast.c index 09bbf6e28..9acb80990 100644 --- a/gs/src/gxclrast.c +++ b/gs/src/gxclrast.c @@ -16,7 +16,7 @@ all copies. */ -/*$Id$ */ + /* Command list interpreter/rasterizer */ #include "memory_.h" #include "gx.h" @@ -90,13 +90,14 @@ cmd_get_w(const byte * p, const byte ** rp) /* * Define the structure for keeping track of the command reading buffer. * - * The ptr member is not used, since normally we want it kept in a - * register. + * The ptr member is only used for passing the current pointer to, and + * receiving an updated pointer from, commands implemented as separate + * procedures: normally it is kept in a register. */ typedef struct command_buf_s { byte *data; /* actual buffer, guaranteed aligned */ uint size; - /*const byte *ptr;*/ /* next byte to be read (see above) */ + const byte *ptr; /* next byte to be read (see above) */ const byte *limit; /* refill warning point */ const byte *end; /* byte just beyond valid data */ stream *s; /* for refilling buffer */ @@ -149,22 +150,55 @@ cmd_read_data(command_buf_t *pcb, byte *ptr, uint rsize, const byte *cbp) return pcb->end; } } +#define cmd_read(ptr, rsize, cbp)\ + cbp = cmd_read_data(&cbuf, ptr, rsize, cbp) + +/* Read a fixed-size value from the command buffer. */ +inline private const byte * +cmd_copy_value(void *pvar, int var_size, const byte *cbp) +{ + memcpy(pvar, cbp, var_size); + return cbp + var_size; +} +#define cmd_get_value(var, cbp)\ + cbp = cmd_copy_value(&var, sizeof(var), cbp) /* * Render one band to a specified target device. Note that if * action == setup, target may be 0. */ +private int read_set_tile_size(P2(command_buf_t *pcb, tile_slot *bits)); +private int read_set_bits(P8(command_buf_t *pcb, tile_slot *bits, + int compress, gx_clist_state *pcls, + gx_strip_bitmap *tile, tile_slot **pslot, + gx_device_clist_reader *cdev, gs_memory_t *mem)); +private int read_set_ht_order(P4(command_buf_t *pcb, gx_device_halftone *pdht, + gx_ht_order **pporder, gs_memory_t *mem)); +private int read_set_ht_data(P8(command_buf_t *pcb, uint *pdata_index, + gx_ht_order *porder, gx_device_halftone *pdht, + gs_halftone_type halftone_type, + gs_imager_state *pis, + gx_device_clist_reader *cdev, + gs_memory_t *mem)); +private int read_begin_image(P5(command_buf_t *pcb, gs_image_t *pim, + int *pnum_planes, gs_int_rect *prect, + const gs_color_space *pcs)); +private int read_put_params(P3(command_buf_t *pcb, + gx_device_clist_reader *cdev, + gs_memory_t *mem)); + private const byte *cmd_read_rect(P3(int, gx_cmd_rect *, const byte *)); private const byte *cmd_read_matrix(P2(gs_matrix *, const byte *)); -private void clist_unpack_short_bits(P5(byte *, const byte *, int, int, uint)); +private const byte *cmd_read_short_bits(P6(command_buf_t *pcb, byte *data, + int width_bytes, int height, + uint raster, const byte *cbp)); private int cmd_select_map(P7(cmd_map_index, bool, gs_imager_state *, gx_ht_order *, frac **, uint *, gs_memory_t *)); private int cmd_resize_halftone(P3(gx_device_halftone *, uint, gs_memory_t *)); -private int cmd_install_ht_order(P3(gx_ht_order *, const gx_ht_order *, - gs_memory_t *)); private int clist_decode_segment(P7(gx_path *, int, fixed[6], gs_fixed_point *, int, int, segment_notes)); + int clist_playback_band(clist_playback_action playback_action, gx_device_clist_reader *cdev, stream *s, @@ -219,15 +253,6 @@ clist_playback_band(clist_playback_action playback_action, int data_x; int code = 0; -#define cmd_get_value(var, cbp)\ - memcpy(&var, cbp, sizeof(var));\ - cbp += sizeof(var) -#define cmd_read(ptr, rsize, cbp)\ - cbp = cmd_read_data(&cbuf, ptr, rsize, cbp) -#define cmd_read_short_bits(ptr, bw, ht, ras, cbp)\ - cbp = cmd_read_data(&cbuf, ptr, (bw) * (ht), cbp);\ - clist_unpack_short_bits(ptr, ptr, bw, ht, ras) - cbuf.data = (byte *)cbuf_storage; cbuf.size = cbuf_size; cbuf.s = s; @@ -248,7 +273,8 @@ in: /* Initialize for a new page. */ } state_tile.id = gx_no_bitmap_id; state_tile.shift = state_tile.rep_shift = 0; - tile_phase.x = tile_phase.y = 0; + tile_phase.x = x0; + tile_phase.y = y0; gx_path_init_local(&path, mem); in_path = false; /* @@ -331,46 +357,11 @@ in: /* Initialize for a new page. */ if_debug0('L', "\n"); continue; case cmd_opv_set_tile_size: - { - uint rep_width, rep_height; - byte bd = *cbp++; - - tile_bits.cb_depth = (bd & 31) + 1; - cmd_getw(rep_width, cbp); - cmd_getw(rep_height, cbp); - if (bd & 0x20) { - cmd_getw(tile_bits.x_reps, cbp); - tile_bits.width = - rep_width * tile_bits.x_reps; - } else { - tile_bits.x_reps = 1, - tile_bits.width = rep_width; - } - if (bd & 0x40) { - cmd_getw(tile_bits.y_reps, cbp); - tile_bits.height = - rep_height * tile_bits.y_reps; - } else { - tile_bits.y_reps = 1, - tile_bits.height = rep_height; - } - if (bd & 0x80) - cmd_getw(tile_bits.rep_shift, cbp); - else - tile_bits.rep_shift = 0; - if_debug6('L', " depth=%d size=(%d,%d), rep_size=(%d,%d), rep_shift=%d\n", - tile_bits.cb_depth, tile_bits.width, - tile_bits.height, rep_width, - rep_height, tile_bits.rep_shift); - tile_bits.shift = - (tile_bits.rep_shift == 0 ? 0 : - (tile_bits.rep_shift * - (tile_bits.height / rep_height)) - % rep_width); - tile_bits.cb_raster = - bitmap_raster(tile_bits.width * - tile_bits.cb_depth); - } + cbuf.ptr = cbp; + code = read_set_tile_size(&cbuf, &tile_bits); + cbp = cbuf.ptr; + if (code < 0) + goto out; continue; case cmd_opv_set_tile_phase: cmd_getw(state.tile_phase.x, cbp); @@ -382,114 +373,14 @@ in: /* Initialize for a new page. */ case cmd_opv_set_tile_bits: bits = tile_bits; compress = 0; - stb:{ - uint rep_width = bits.width / bits.x_reps; - uint rep_height = bits.height / bits.y_reps; - uint index; - ulong offset; - uint width_bits = rep_width * bits.cb_depth; - uint width_bytes; - uint bytes = - clist_bitmap_bytes(width_bits, rep_height, - compress | - (rep_width < bits.width ? - decompress_spread : 0) | - decompress_elsewhere, - &width_bytes, - (uint *) & raster); - byte *data; - - cmd_getw(index, cbp); - cmd_getw(offset, cbp); - if_debug2('L', " index=%d offset=%lu\n", - state.tile_index, offset); - state.tile_index = index; - cdev->tile_table[state.tile_index].offset = - offset; - state_slot = - (tile_slot *) (cdev->chunk.data + offset); - *state_slot = bits; - state_tile.data = data = - (byte *) (state_slot + 1); -#ifdef DEBUG - state_slot->index = state.tile_index; -#endif - if (compress) { /* Decompress the image data. */ - /* We'd like to share this code */ - /* with the similar code in copy_*, */ - /* but right now we don't see how. */ - stream_cursor_read r; - stream_cursor_write w; - - /* We don't know the data length a */ - /* priori, so to be conservative, */ - /* we read the uncompressed size. */ - uint cleft = cbuf.end - cbp; - - if (cleft < bytes) { - uint nread = cbuf_size - cleft; - - memmove(cbuf.data, cbp, cleft); - cbuf.end_status = sgets(s, cbuf.data + cleft, nread, &nread); - set_cb_end(&cbuf, cbuf.data + cleft + nread); - cbp = cbuf.data; - } - r.ptr = cbp - 1; - r.limit = cbuf.end - 1; - w.ptr = data - 1; - w.limit = w.ptr + bytes; - switch (compress) { - case cmd_compress_rle: - { - stream_RLD_state sstate; - - clist_rld_init(&sstate); - (*s_RLD_template.process) - ((stream_state *) & sstate, &r, &w, true); - } - break; - case cmd_compress_cfe: - { - stream_CFD_state sstate; - - clist_cfd_init(&sstate, - width_bytes << 3 /*width_bits */ , - rep_height, mem); - (*s_CFD_template.process) - ((stream_state *) & sstate, &r, &w, true); - (*s_CFD_template.release) - ((stream_state *) & sstate); - } - break; - default: - goto bad_op; - } - cbp = r.ptr + 1; - } else if (rep_height > 1 && - width_bytes != bits.cb_raster - ) { - cmd_read_short_bits(data, width_bytes, - rep_height, bits.cb_raster, cbp); - } else { - cmd_read(data, bytes, cbp); - } - if (bits.width > rep_width) - bits_replicate_horizontally(data, - rep_width * bits.cb_depth, rep_height, - bits.cb_raster, - bits.width * bits.cb_depth, - bits.cb_raster); - if (bits.height > rep_height) - bits_replicate_vertically(data, - rep_height, bits.cb_raster, - bits.height); -#ifdef DEBUG - if (gs_debug_c('L')) - cmd_print_bits(data, bits.width, - bits.height, - bits.cb_raster); -#endif - } + stb: + cbuf.ptr = cbp; + code = read_set_bits(&cbuf, &bits, compress, + &state, &state_tile, &state_slot, + cdev, mem); + cbp = cbuf.ptr; + if (code < 0) + goto out; goto stp; case cmd_opv_set_bits: compress = *cbp & 3; @@ -591,139 +482,35 @@ in: /* Initialize for a new page. */ if_debug0('L', "\n"); continue; case cmd_opv_set_ht_order: - { - int index; - gx_ht_order order; - - cmd_getw(index, cbp); - if (index == 0) - porder = &dev_ht.order; - else { - gx_ht_order_component *pcomp = - &dev_ht.components[index - 1]; - - cmd_getw(pcomp->cname, cbp); - if_debug1('L', " cname=%lu", - (ulong) pcomp->cname); - porder = &pcomp->corder; - } - order = *porder; - cmd_getw(order.width, cbp); - cmd_getw(order.height, cbp); - cmd_getw(order.raster, cbp); - cmd_getw(order.shift, cbp); - cmd_getw(order.num_levels, cbp); - cmd_getw(order.num_bits, cbp); - if_debug7('L', " index=%d size=(%d,%d) raster=%d shift=%d num_levels=%d num_bits=%d\n", - index, order.width, order.height, - order.raster, order.shift, - order.num_levels, order.num_bits); - code = - cmd_install_ht_order(porder, &order, mem); - if (code < 0) - goto out; - } + cbuf.ptr = cbp; + code = read_set_ht_order(&cbuf, &dev_ht, &porder, mem); + cbp = cbuf.ptr; + if (code < 0) + goto out; ht_data_index = 0; - continue; - case cmd_opv_set_ht_data: + /* + * Free the relevant cache, because its sizes + * are probably not correct any more. + */ { - int n = *cbp++; + gx_ht_cache *pcache = porder->cache; - if (ht_data_index < porder->num_levels) { /* Setting levels */ - byte *lptr = (byte *) - (porder->levels + ht_data_index); - - cmd_read(lptr, n * sizeof(*porder->levels), - cbp); -#ifdef DEBUG - if (gs_debug_c('L')) { - int i; - - dprintf1(" levels[%u]", ht_data_index); - for (i = 0; i < n; ++i) - dprintf1(" %u", - porder->levels[ht_data_index + i]); - dputc('\n'); - } -#endif - } else { /* Setting bits */ - byte *bptr = (byte *) - (porder->bits + - (ht_data_index - porder->num_levels)); - - cmd_read(bptr, n * sizeof(*porder->bits), - cbp); -#ifdef DEBUG - if (gs_debug_c('L')) { - int i; - - dprintf1(" bits[%u]", ht_data_index - porder->num_levels); - for (i = 0; i < n; ++i) { - const gx_ht_bit *pb = - &porder->bits[ht_data_index - porder->num_levels + i]; - - dprintf2(" (%u,0x%lx)", - pb->offset, - (ulong) pb->mask); - } - dputc('\n'); - } -#endif - } - ht_data_index += n; - } - /* If this is the end of the data, */ - /* install the (device) halftone. */ - if (porder == - (dev_ht.components != 0 ? - &dev_ht.components[0].corder : - &dev_ht.order) && - ht_data_index == porder->num_levels + - porder->num_bits - ) { /* Make sure we have a halftone cache. */ - uint i; - - if (imager_state.ht_cache == 0) { - gx_ht_cache *pcache = - gx_ht_alloc_cache(mem, - porder->num_levels + 2, - gx_ht_cache_default_bits()); - - if (pcache == 0) { - code = gs_note_error(gs_error_VMerror); - goto out; - } - imager_state.ht_cache = pcache; + if (pcache) { + if (pcache != imager_state.ht_cache) + gx_ht_free_cache(mem, pcache); + porder->cache = 0; } - for (i = 1; i < dev_ht.num_comp; ++i) { - gx_ht_order *pco = - &dev_ht.components[i].corder; - - if (!pco->cache) { - gx_ht_cache *pcache = - gx_ht_alloc_cache(mem, 1, - pco->raster * (pco->num_bits / - pco->width)); - - if (pcache == 0) { - code = gs_note_error(gs_error_VMerror); - goto out; - } - pco->cache = pcache; - gx_ht_init_cache(pcache, pco); - } - } - if (dev_ht.num_comp) { - dev_ht.components[0].corder.cache = - imager_state.ht_cache; - dev_ht.order = - dev_ht.components[0].corder; - } - gx_imager_dev_ht_install(&imager_state, - &dev_ht, halftone_type, - (const gx_device *)cdev); } continue; + case cmd_opv_set_ht_data: + cbuf.ptr = cbp; + code = read_set_ht_data(&cbuf, &ht_data_index, porder, + &dev_ht, halftone_type, + &imager_state, cdev, mem); + cbp = cbuf.ptr; + if (code < 0) + goto out; + continue; case cmd_opv_end_page: if_debug0('L', "\n"); /* @@ -892,7 +679,7 @@ in: /* Initialize for a new page. */ clist_bitmap_bytes(width_bits, state.rect.height, op & 3, &width_bytes, - (uint *) & raster); + (uint *)&raster); /* copy_mono and copy_color/alpha */ /* ensure that the bits will fit in a single buffer, */ /* even after decompression if compressed. */ @@ -936,7 +723,7 @@ in: /* Initialize for a new page. */ clist_rld_init(&sstate); /* The process procedure can't fail. */ (*s_RLD_template.process) - ((stream_state *) & sstate, &r, &w, true); + ((stream_state *)&sstate, &r, &w, true); } break; case cmd_compress_cfe: @@ -948,9 +735,9 @@ in: /* Initialize for a new page. */ state.rect.height, mem); /* The process procedure can't fail. */ (*s_CFD_template.process) - ((stream_state *) & sstate, &r, &w, true); + ((stream_state *)&sstate, &r, &w, true); (*s_CFD_template.release) - ((stream_state *) & sstate); + ((stream_state *)&sstate); } break; default: @@ -962,9 +749,9 @@ in: /* Initialize for a new page. */ width_bytes != raster ) { source = data_bits; - cmd_read_short_bits(source, width_bytes, - state.rect.height, - raster, cbp); + cbp = cmd_read_short_bits(&cbuf, source, width_bytes, + state.rect.height, + raster, cbp); } else { cmd_read(cbuf.data, bytes, cbp); source = cbuf.data; @@ -1159,7 +946,7 @@ in: /* Initialize for a new page. */ gx_cpath_accum_begin(&clip_accum, mem); gx_cpath_accum_set_cbox(&clip_accum, &target_box); - tdev = (gx_device *) & clip_accum; + tdev = (gx_device *)&clip_accum; clip_save.lop_enabled = state.lop_enabled; clip_save.fill_adjust = imager_state.fill_adjust; @@ -1231,153 +1018,19 @@ in: /* Initialize for a new page. */ } break; case cmd_opv_begin_image: + cbuf.ptr = cbp; + code = read_begin_image(&cbuf, &image, + &image_num_planes, + &image_rect, pcs); + cbp = cbuf.ptr; + if (code < 0) + goto out; { - byte b = *cbp++; - int bpci = b >> 5; - static const byte bpc[6] = - {1, 1, 2, 4, 8, 12}; gx_drawing_color devc; - int num_components; - gs_image_format_t format; - if (bpci == 0) - gs_image_t_init_mask(&image, false); - else - gs_image_t_init(&image, pcs); - if (b & (1 << 4)) { - byte b2 = *cbp++; - - format = b2 >> 6; - image.Interpolate = (b2 & (1 << 5)) != 0; - image.Alpha = - (gs_image_alpha_t) ((b2 >> 3) & 3); - } else { - format = gs_image_format_chunky; - } - cmd_getw(image.Width, cbp); - cmd_getw(image.Height, cbp); - if_debug4('L', " BPCi=%d I=%d size=(%d,%d)", - bpci, (b & 0x10) != 0, - image.Width, image.Height); - if (b & (1 << 3)) { /* Non-standard ImageMatrix */ - cbp = cmd_read_matrix( - &image.ImageMatrix, cbp); - if_debug6('L', " matrix=[%g %g %g %g %g %g]", - image.ImageMatrix.xx, - image.ImageMatrix.xy, - image.ImageMatrix.yx, - image.ImageMatrix.yy, - image.ImageMatrix.tx, - image.ImageMatrix.ty); - } else { - image.ImageMatrix.xx = image.Width; - image.ImageMatrix.xy = 0; - image.ImageMatrix.yx = 0; - image.ImageMatrix.yy = -image.Height; - image.ImageMatrix.tx = 0; - image.ImageMatrix.ty = image.Height; - } - image.BitsPerComponent = bpc[bpci]; - if (bpci == 0) { - num_components = 1; - } else { - image.ColorSpace = pcs; - if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed) { - image.Decode[0] = 0; - image.Decode[1] = - (1 << image.BitsPerComponent) - 1; - } else { - static const float decode01[] = - { - 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 - }; - - memcpy(image.Decode, decode01, - sizeof(image.Decode)); - } - num_components = - gs_color_space_num_components(pcs); - } - switch (format) { - case gs_image_format_chunky: - image_num_planes = 1; - break; - case gs_image_format_component_planar: - image_num_planes = num_components; - break; - case gs_image_format_bit_planar: - image_num_planes = num_components * - image.BitsPerComponent; - break; - default: - goto bad_op; - } - if (b & (1 << 2)) { /* Non-standard Decode */ - byte dflags = *cbp++; - int i; - - for (i = 0; i < num_components * 2; - dflags <<= 2, i += 2 - ) - switch ((dflags >> 6) & 3) { - case 0: /* default */ - break; - case 1: /* swapped default */ - image.Decode[i] = - image.Decode[i + 1]; - image.Decode[i + 1] = 0; - break; - case 3: - cmd_get_value(image.Decode[i], - cbp); - /* falls through */ - case 2: - cmd_get_value(image.Decode[i + 1], - cbp); - } -#ifdef DEBUG - if (gs_debug_c('L')) { - dputs(" decode=["); - for (i = 0; i < num_components * 2; - ++i - ) - dprintf1("%g ", image.Decode[i]); - dputc(']'); - } -#endif - } - image.adjust = false; - if (b & (1 << 1)) { - if (image.ImageMask) - image.adjust = true; - else - image.CombineWithColor = true; - if_debug1('L', " %s", - (image.ImageMask ? " adjust" : - " CWC")); - } - if (b & (1 << 0)) { /* Non-standard rectangle */ - uint diff; - - cmd_getw(image_rect.p.x, cbp); - cmd_getw(image_rect.p.y, cbp); - cmd_getw(diff, cbp); - image_rect.q.x = image.Width - diff; - cmd_getw(diff, cbp); - image_rect.q.y = image.Height - diff; - if_debug4('L', " rect=(%d,%d),(%d,%d)", - image_rect.p.x, image_rect.p.y, - image_rect.q.x, image_rect.q.y); - } else { - image_rect.p.x = 0; - image_rect.p.y = 0; - image_rect.q.x = image.Width; - image_rect.q.y = image.Height; - } - if_debug0('L', "\n"); color_set_pure(&devc, state.colors[1]); code = (*dev_proc(tdev, begin_image)) - (tdev, &imager_state, &image, format, + (tdev, &imager_state, &image, image.format, &image_rect, &devc, pcpath, mem, &image_info); if (code < 0) @@ -1497,70 +1150,16 @@ in: /* Initialize for a new page. */ #undef dcl } continue; - case cmd_opv_put_params: { - gs_c_param_list param_list; - uint cleft; - uint rleft; - bool alloc_data_on_heap = false; - byte *param_buf; - uint param_length; - - cmd_get_value(param_length, cbp); - if_debug1('L', " length=%d\n", param_length); - code = 0; - if (param_length == 0) - break; - - /* Make sure entire serialized param list is in cbuf */ - /* + force void* alignment */ - cbp = top_up_cbuf(&cbuf, cbp); - if (cbuf.end - cbp >= param_length) { - param_buf = (byte *)cbp; - cbp += param_length; - } else { - /* NOTE: param_buf must be maximally aligned */ - param_buf = gs_alloc_bytes(mem, param_length, - "clist put_params"); - if (param_buf == 0) { - code = gs_note_error(gs_error_VMerror); - goto out; - } - alloc_data_on_heap = true; - cleft = cbuf.end - cbp; - rleft = param_length - cleft; - memmove(param_buf, cbp, cleft); - sgets(s, param_buf + cleft, rleft, &rleft); - cbp = cbuf.end; /* force refill */ - } - - /* - * Create a gs_c_param_list & expand into it. - * NB that gs_c_param_list doesn't copy objects into - * it, but rather keeps *pointers* to what's passed. - * That's OK because the serialized format keeps enough - * space to hold expanded versions of the structures, - * but this means we cannot deallocate source buffer - * until the gs_c_param_list is deleted. - */ - gs_c_param_list_write(¶m_list, mem); - code = gs_param_list_unserialize - ( (gs_param_list *)¶m_list, param_buf ); - if (code >= 0 && code != param_length) - code = gs_error_unknownerror; /* must match */ - if (code >= 0) { - gs_c_param_list_read(¶m_list); - code = (*dev_proc(cdev, put_params)) - ((gx_device *)cdev, - (gs_param_list *)¶m_list); - } - gs_c_param_list_release(¶m_list); - if (alloc_data_on_heap) - gs_free_object(mem, param_buf, "clist put_params"); + case cmd_opv_put_params: + cbuf.ptr = cbp; + code = read_put_params(&cbuf, cdev, mem); + cbp = cbuf.ptr; + if (code > 0) + break; /* empty list */ if (code < 0) goto out; if (playback_action == playback_action_setup) goto out; - } break; default: goto bad_op; @@ -1862,15 +1461,551 @@ in: /* Initialize for a new page. */ return code; } -/* Unpack a short bitmap */ -private void -clist_unpack_short_bits(byte * dest, const byte * src, int width_bytes, - int height, uint raster) +/* ---------------- Individual commands ---------------- */ + +/* + * These single-use procedures implement a few large individual commands, + * primarily for readability but also to avoid overflowing compilers' + * optimization limits. They all take the command buffer as their first + * parameter (pcb), assume that the current buffer pointer is in pcb->ptr, + * and update it there. + */ + +private int +read_set_tile_size(command_buf_t *pcb, tile_slot *bits) +{ + const byte *cbp = pcb->ptr; + uint rep_width, rep_height; + byte bd = *cbp++; + + bits->cb_depth = (bd & 31) + 1; + cmd_getw(rep_width, cbp); + cmd_getw(rep_height, cbp); + if (bd & 0x20) { + cmd_getw(bits->x_reps, cbp); + bits->width = rep_width * bits->x_reps; + } else { + bits->x_reps = 1; + bits->width = rep_width; + } + if (bd & 0x40) { + cmd_getw(bits->y_reps, cbp); + bits->height = rep_height * bits->y_reps; + } else { + bits->y_reps = 1; + bits->height = rep_height; + } + if (bd & 0x80) + cmd_getw(bits->rep_shift, cbp); + else + bits->rep_shift = 0; + if_debug6('L', " depth=%d size=(%d,%d), rep_size=(%d,%d), rep_shift=%d\n", + bits->cb_depth, bits->width, + bits->height, rep_width, + rep_height, bits->rep_shift); + bits->shift = + (bits->rep_shift == 0 ? 0 : + (bits->rep_shift * (bits->height / rep_height)) % rep_width); + bits->cb_raster = bitmap_raster(bits->width * bits->cb_depth); + pcb->ptr = cbp; + return 0; +} + +private int +read_set_bits(command_buf_t *pcb, tile_slot *bits, int compress, + gx_clist_state *pcls, gx_strip_bitmap *tile, tile_slot **pslot, + gx_device_clist_reader *cdev, gs_memory_t *mem) +{ + const byte *cbp = pcb->ptr; + uint rep_width = bits->width / bits->x_reps; + uint rep_height = bits->height / bits->y_reps; + uint index; + ulong offset; + uint width_bits = rep_width * bits->cb_depth; + uint width_bytes; + uint raster; + uint bytes = + clist_bitmap_bytes(width_bits, rep_height, + compress | + (rep_width < bits->width ? + decompress_spread : 0) | + decompress_elsewhere, + &width_bytes, + (uint *)&raster); + byte *data; + tile_slot *slot; + + cmd_getw(index, cbp); + cmd_getw(offset, cbp); + if_debug2('L', " index=%d offset=%lu\n", pcls->tile_index, offset); + pcls->tile_index = index; + cdev->tile_table[pcls->tile_index].offset = offset; + slot = (tile_slot *)(cdev->chunk.data + offset); + *pslot = slot; + *slot = *bits; + tile->data = data = (byte *)(slot + 1); +#ifdef DEBUG + slot->index = pcls->tile_index; +#endif + if (compress) { + /* + * Decompress the image data. We'd like to share this code with the + * similar code in copy_*, but right now we don't see how. + */ + stream_cursor_read r; + stream_cursor_write w; + /* + * We don't know the data length a priori, so to be conservative, we + * read the uncompressed size. + */ + uint cleft = pcb->end - cbp; + + if (cleft < bytes) { + uint nread = cbuf_size - cleft; + + memmove(pcb->data, cbp, cleft); + pcb->end_status = sgets(pcb->s, pcb->data + cleft, nread, &nread); + set_cb_end(pcb, pcb->data + cleft + nread); + cbp = pcb->data; + } + r.ptr = cbp - 1; + r.limit = pcb->end - 1; + w.ptr = data - 1; + w.limit = w.ptr + bytes; + switch (compress) { + case cmd_compress_rle: + { + stream_RLD_state sstate; + + clist_rld_init(&sstate); + (*s_RLD_template.process) + ((stream_state *)&sstate, &r, &w, true); + } + break; + case cmd_compress_cfe: + { + stream_CFD_state sstate; + + clist_cfd_init(&sstate, + width_bytes << 3 /*width_bits */ , + rep_height, mem); + (*s_CFD_template.process) + ((stream_state *)&sstate, &r, &w, true); + (*s_CFD_template.release) + ((stream_state *)&sstate); + } + break; + default: + return_error(gs_error_unregistered); + } + cbp = r.ptr + 1; + } else if (rep_height > 1 && width_bytes != bits->cb_raster) { + cbp = cmd_read_short_bits(pcb, data, + width_bytes, rep_height, + bits->cb_raster, cbp); + } else { + cbp = cmd_read_data(pcb, data, bytes, cbp); + } + if (bits->width > rep_width) + bits_replicate_horizontally(data, + rep_width * bits->cb_depth, rep_height, + bits->cb_raster, + bits->width * bits->cb_depth, + bits->cb_raster); + if (bits->height > rep_height) + bits_replicate_vertically(data, + rep_height, bits->cb_raster, + bits->height); +#ifdef DEBUG + if (gs_debug_c('L')) + cmd_print_bits(data, bits->width, bits->height, bits->cb_raster); +#endif + pcb->ptr = cbp; + return 0; +} + +private int +read_set_ht_order(command_buf_t *pcb, gx_device_halftone *pdht, + gx_ht_order **pporder, gs_memory_t *mem) +{ + const byte *cbp = pcb->ptr; + gx_ht_order *porder; + uint *levels; + gx_ht_bit *bits; + int index; + gx_ht_order new_order; + + cmd_getw(index, cbp); + if (index == 0) + porder = &pdht->order; + else { + gx_ht_order_component *pcomp = &pdht->components[index - 1]; + + cmd_getw(pcomp->cname, cbp); + if_debug1('L', " cname=%lu", (ulong) pcomp->cname); + porder = &pcomp->corder; + } + *pporder = porder; + new_order = *porder; + cmd_getw(new_order.width, cbp); + cmd_getw(new_order.height, cbp); + cmd_getw(new_order.raster, cbp); + cmd_getw(new_order.shift, cbp); + cmd_getw(new_order.num_levels, cbp); + cmd_getw(new_order.num_bits, cbp); + pcb->ptr = cbp; + if_debug7('L', " index=%d size=(%d,%d) raster=%d shift=%d num_levels=%d num_bits=%d\n", + index, new_order.width, new_order.height, + new_order.raster, new_order.shift, + new_order.num_levels, new_order.num_bits); + levels = porder->levels; + bits = porder->bits; + /* + * Note that for resizing a byte array, the element size is 1 byte, + * not the element size given to alloc_byte_array! + */ + if (new_order.num_levels > porder->num_levels) { + if (levels == 0) + levels = (uint *) gs_alloc_byte_array(mem, new_order.num_levels, + sizeof(*levels), + "ht order(levels)"); + else + levels = gs_resize_object(mem, levels, + new_order.num_levels * sizeof(*levels), + "ht order(levels)"); + if (levels == 0) + return_error(gs_error_VMerror); + /* Update porder in case we bail out. */ + porder->levels = levels; + porder->num_levels = new_order.num_levels; + } + if (new_order.num_bits > porder->num_bits) { + if (bits == 0) + bits = (gx_ht_bit *) gs_alloc_byte_array(mem, new_order.num_bits, + sizeof(*bits), + "ht order(bits)"); + else + bits = gs_resize_object(mem, bits, + new_order.num_bits * sizeof(*bits), + "ht order(bits)"); + if (bits == 0) + return_error(gs_error_VMerror); + } + *porder = new_order; + porder->levels = levels; + porder->bits = bits; + porder->full_height = ht_order_full_height(porder); + return 0; +} + +private int +read_set_ht_data(command_buf_t *pcb, uint *pdata_index, gx_ht_order *porder, + gx_device_halftone *pdht, gs_halftone_type halftone_type, + gs_imager_state *pis, gx_device_clist_reader *cdev, + gs_memory_t *mem) +{ + const byte *cbp = pcb->ptr; + int n = *cbp++; + + if (*pdata_index < porder->num_levels) { /* Setting levels */ + byte *lptr = (byte *)(porder->levels + *pdata_index); + + cbp = cmd_read_data(pcb, lptr, n * sizeof(*porder->levels), cbp); +#ifdef DEBUG + if (gs_debug_c('L')) { + int i; + + dprintf1(" levels[%u]", *pdata_index); + for (i = 0; i < n; ++i) + dprintf1(" %u", + porder->levels[*pdata_index + i]); + dputc('\n'); + } +#endif + } else { /* Setting bits */ + byte *bptr = (byte *) + (porder->bits + (*pdata_index - porder->num_levels)); + + cbp = cmd_read_data(pcb, bptr, n * sizeof(*porder->bits), cbp); +#ifdef DEBUG + if (gs_debug_c('L')) { + int i; + + dprintf1(" bits[%u]", *pdata_index - porder->num_levels); + for (i = 0; i < n; ++i) { + const gx_ht_bit *pb = + &porder->bits[*pdata_index - porder->num_levels + i]; + + dprintf2(" (%u,0x%lx)", + pb->offset, + (ulong) pb->mask); + } + dputc('\n'); + } +#endif + } + *pdata_index += n; + /* If this is the end of the data, */ + /* install the (device) halftone. */ + if (porder == + (pdht->components != 0 ? + &pdht->components[0].corder : + &pdht->order) && + *pdata_index == porder->num_levels + porder->num_bits + ) { /* Make sure we have a halftone cache. */ + uint i; + + if (pis->ht_cache == 0) { + gx_ht_cache *pcache = + gx_ht_alloc_cache(mem, + porder->num_levels + 2, + gx_ht_cache_default_bits()); + + if (pcache == 0) + return_error(gs_error_VMerror); + pis->ht_cache = pcache; + } + for (i = 1; i < pdht->num_comp; ++i) { + gx_ht_order *pco = &pdht->components[i].corder; + + if (!pco->cache) { + gx_ht_cache *pcache = + gx_ht_alloc_cache(mem, 1, + pco->raster * (pco->num_bits / + pco->width)); + + if (pcache == 0) + return_error(gs_error_VMerror); + pco->cache = pcache; + gx_ht_init_cache(pco->cache, pco); + } + } + if (pdht->num_comp) { + pdht->components[0].corder.cache = pis->ht_cache; + pdht->order = pdht->components[0].corder; + } + gx_imager_dev_ht_install(pis, pdht, halftone_type, + (const gx_device *)cdev); + } + pcb->ptr = cbp; + return 0; +} + +private int +read_begin_image(command_buf_t *pcb, gs_image_t *pim, int *pnum_planes, + gs_int_rect *prect, const gs_color_space *pcs) +{ + const byte *cbp = pcb->ptr; + byte b = *cbp++; + int bpci = b >> 5; + static const byte bpc[6] = {1, 1, 2, 4, 8, 12}; + int num_components; + gs_image_format_t format; + + if (bpci == 0) + gs_image_t_init_mask(pim, false); + else + gs_image_t_init(pim, pcs); + if (b & (1 << 4)) { + byte b2 = *cbp++; + + format = b2 >> 6; + pim->Interpolate = (b2 & (1 << 5)) != 0; + pim->Alpha = (gs_image_alpha_t) ((b2 >> 3) & 3); + } else { + format = gs_image_format_chunky; + } + pim->format = format; + cmd_getw(pim->Width, cbp); + cmd_getw(pim->Height, cbp); + if_debug4('L', " BPCi=%d I=%d size=(%d,%d)", + bpci, (b & 0x10) != 0, pim->Width, pim->Height); + if (b & (1 << 3)) { /* Non-standard ImageMatrix */ + cbp = cmd_read_matrix( + &pim->ImageMatrix, cbp); + if_debug6('L', " matrix=[%g %g %g %g %g %g]", + pim->ImageMatrix.xx, pim->ImageMatrix.xy, + pim->ImageMatrix.yx, pim->ImageMatrix.yy, + pim->ImageMatrix.tx, pim->ImageMatrix.ty); + } else { + pim->ImageMatrix.xx = pim->Width; + pim->ImageMatrix.xy = 0; + pim->ImageMatrix.yx = 0; + pim->ImageMatrix.yy = -pim->Height; + pim->ImageMatrix.tx = 0; + pim->ImageMatrix.ty = pim->Height; + } + pim->BitsPerComponent = bpc[bpci]; + if (bpci == 0) { + num_components = 1; + } else { + pim->ColorSpace = pcs; + if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed) { + pim->Decode[0] = 0; + pim->Decode[1] = (1 << pim->BitsPerComponent) - 1; + } else { + static const float decode01[] = { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + }; + + memcpy(pim->Decode, decode01, sizeof(pim->Decode)); + } + num_components = gs_color_space_num_components(pcs); + } + switch (format) { + case gs_image_format_chunky: + *pnum_planes = 1; + break; + case gs_image_format_component_planar: + *pnum_planes = num_components; + break; + case gs_image_format_bit_planar: + *pnum_planes = num_components * pim->BitsPerComponent; + break; + default: + return_error(gs_error_unregistered); + } + if (b & (1 << 2)) { /* Non-standard Decode */ + byte dflags = *cbp++; + int i; + + for (i = 0; i < num_components * 2; dflags <<= 2, i += 2) + switch ((dflags >> 6) & 3) { + case 0: /* default */ + break; + case 1: /* swapped default */ + pim->Decode[i] = pim->Decode[i + 1]; + pim->Decode[i + 1] = 0; + break; + case 3: + cmd_get_value(pim->Decode[i], cbp); + /* falls through */ + case 2: + cmd_get_value(pim->Decode[i + 1], cbp); + } +#ifdef DEBUG + if (gs_debug_c('L')) { + dputs(" decode=["); + for (i = 0; i < num_components * 2; ++i) + dprintf1("%g ", pim->Decode[i]); + dputc(']'); + } +#endif + } + pim->adjust = false; + if (b & (1 << 1)) { + if (pim->ImageMask) + pim->adjust = true; + else + pim->CombineWithColor = true; + if_debug1('L', " %s", + (pim->ImageMask ? " adjust" : " CWC")); + } + if (b & (1 << 0)) { /* Non-standard rectangle */ + uint diff; + + cmd_getw(prect->p.x, cbp); + cmd_getw(prect->p.y, cbp); + cmd_getw(diff, cbp); + prect->q.x = pim->Width - diff; + cmd_getw(diff, cbp); + prect->q.y = pim->Height - diff; + if_debug4('L', " rect=(%d,%d),(%d,%d)", + prect->p.x, prect->p.y, + prect->q.x, prect->q.y); + } else { + prect->p.x = 0; + prect->p.y = 0; + prect->q.x = pim->Width; + prect->q.y = pim->Height; + } + if_debug0('L', "\n"); + pcb->ptr = cbp; + return 0; +} + +private int +read_put_params(command_buf_t *pcb, gx_device_clist_reader *cdev, + gs_memory_t *mem) +{ + const byte *cbp = pcb->ptr; + gs_c_param_list param_list; + uint cleft; + uint rleft; + bool alloc_data_on_heap = false; + byte *param_buf; + uint param_length; + int code = 0; + + cmd_get_value(param_length, cbp); + if_debug1('L', " length=%d\n", param_length); + if (param_length == 0) { + code = 1; /* empty list */ + goto out; + } + + /* Make sure entire serialized param list is in cbuf */ + /* + force void* alignment */ + cbp = top_up_cbuf(pcb, cbp); + if (pcb->end - cbp >= param_length) { + param_buf = (byte *)cbp; + cbp += param_length; + } else { + /* NOTE: param_buf must be maximally aligned */ + param_buf = gs_alloc_bytes(mem, param_length, + "clist put_params"); + if (param_buf == 0) { + code = gs_note_error(gs_error_VMerror); + goto out; + } + alloc_data_on_heap = true; + cleft = pcb->end - cbp; + rleft = param_length - cleft; + memmove(param_buf, cbp, cleft); + pcb->end_status = sgets(pcb->s, param_buf + cleft, rleft, &rleft); + cbp = pcb->end; /* force refill */ + } + + /* + * Create a gs_c_param_list & expand into it. + * NB that gs_c_param_list doesn't copy objects into + * it, but rather keeps *pointers* to what's passed. + * That's OK because the serialized format keeps enough + * space to hold expanded versions of the structures, + * but this means we cannot deallocate source buffer + * until the gs_c_param_list is deleted. + */ + gs_c_param_list_write(¶m_list, mem); + code = gs_param_list_unserialize + ( (gs_param_list *)¶m_list, param_buf ); + if (code >= 0 && code != param_length) + code = gs_error_unknownerror; /* must match */ + if (code >= 0) { + gs_c_param_list_read(¶m_list); + code = (*dev_proc(cdev, put_params)) + ((gx_device *)cdev, (gs_param_list *)¶m_list); + } + gs_c_param_list_release(¶m_list); + if (alloc_data_on_heap) + gs_free_object(mem, param_buf, "clist put_params"); + +out: + pcb->ptr = cbp; + return code; +} + +/* ---------------- Utilities ---------------- */ + +/* Read and unpack a short bitmap */ +private const byte * +cmd_read_short_bits(command_buf_t *pcb, byte *data, int width_bytes, + int height, uint raster, const byte *cbp) { uint bytes = width_bytes * height; - const byte *pdata = src + bytes; - byte *udata = dest + height * raster; + const byte *pdata = data /*src*/ + bytes; + byte *udata = data /*dest*/ + height * raster; + cbp = cmd_read_data(pcb, data, width_bytes * height, cbp); while (--height >= 0) { udata -= raster, pdata -= width_bytes; switch (width_bytes) { @@ -1892,6 +2027,7 @@ clist_unpack_short_bits(byte * dest, const byte * src, int width_bytes, case 0:; /* shouldn't happen */ } } + return cbp; } /* Read a rectangle. */ @@ -2028,52 +2164,6 @@ alloc: if (!load) { return 0; } -/* Install a halftone order, resizing the bits and levels if necessary. */ -private int -cmd_install_ht_order(gx_ht_order * porder, const gx_ht_order * pnew, - gs_memory_t * mem) -{ - uint *levels = porder->levels; - gx_ht_bit *bits = porder->bits; - - /* - * Note that for resizing a byte array, the element size is 1 byte, - * not the element size given to alloc_byte_array! - */ - if (pnew->num_levels > porder->num_levels) { - if (levels == 0) - levels = (uint *) gs_alloc_byte_array(mem, pnew->num_levels, - sizeof(*levels), - "ht order(levels)"); - else - levels = gs_resize_object(mem, levels, - pnew->num_levels * sizeof(*levels), - "ht order(levels)"); - if (levels == 0) - return_error(gs_error_VMerror); - /* Update porder in case we bail out. */ - porder->levels = levels; - porder->num_levels = pnew->num_levels; - } - if (pnew->num_bits > porder->num_bits) { - if (bits == 0) - bits = (gx_ht_bit *) gs_alloc_byte_array(mem, pnew->num_bits, - sizeof(*bits), - "ht order(bits)"); - else - bits = gs_resize_object(mem, bits, - pnew->num_bits * sizeof(*bits), - "ht order(bits)"); - if (bits == 0) - return_error(gs_error_VMerror); - } - *porder = *pnew; - porder->levels = levels; - porder->bits = bits; - porder->full_height = ht_order_full_height(porder); - return 0; -} - /* Resize the halftone components array if necessary. */ private int cmd_resize_halftone(gx_device_halftone * pdht, uint num_comp, |