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/gxclpath.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/gxclpath.c')
-rw-r--r-- | gs/src/gxclpath.c | 2030 |
1 files changed, 1034 insertions, 996 deletions
diff --git a/gs/src/gxclpath.c b/gs/src/gxclpath.c index 3bb581efe..8aeb57a24 100644 --- a/gs/src/gxclpath.c +++ b/gs/src/gxclpath.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. + */ /* gxclpath.c */ /* Higher-level path operations for band lists */ @@ -24,11 +24,11 @@ #include "gpcheck.h" #include "gserrors.h" #include "gxdevice.h" -#include "gxdevmem.h" /* must precede gxcldev.h */ +#include "gxdevmem.h" /* must precede gxcldev.h */ #include "gxcldev.h" #include "gxclpath.h" #include "gxcolor2.h" -#include "gxpaint.h" /* for gx_fill/stroke_params */ +#include "gxpaint.h" /* for gx_fill/stroke_params */ #include "gzpath.h" #include "gzcpath.h" @@ -37,12 +37,14 @@ /* Statistics */ #ifdef DEBUG ulong cmd_diffs[5]; + #endif /* Forward declarations */ -private int cmd_put_path(P8(gx_device_clist_writer *cldev, - gx_clist_state *pcls, const gx_path *ppath, fixed ymin, fixed ymax, byte op, - bool implicit_close, segment_notes keep_notes)); +private int cmd_put_path(P8(gx_device_clist_writer * cldev, + gx_clist_state * pcls, const gx_path * ppath, fixed ymin, fixed ymax, byte op, + bool implicit_close, segment_notes keep_notes)); + /* Driver procedures */ private dev_proc_fill_path(clist_fill_path); private dev_proc_stroke_path(clist_stroke_path); @@ -50,27 +52,31 @@ private dev_proc_stroke_path(clist_stroke_path); /* ------ Define the extensions to the command set ------ */ #ifdef DEBUG -private const char *cmd_misc2_op_names[16] = { cmd_misc2_op_name_strings }; -private const char *cmd_segment_op_names[16] = { cmd_segment_op_name_strings }; -private const char *cmd_path_op_names[16] = { cmd_path_op_name_strings }; +private const char *cmd_misc2_op_names[16] = +{cmd_misc2_op_name_strings}; +private const char *cmd_segment_op_names[16] = +{cmd_segment_op_name_strings}; +private const char *cmd_path_op_names[16] = +{cmd_path_op_name_strings}; + #endif /* Initialize the extensions to the command name table. */ void -gs_clpath_init(gs_memory_t *mem) +gs_clpath_init(gs_memory_t * mem) { #ifdef DEBUG - cmd_op_names[cmd_op_misc2 >> 4] = "(misc2)"; - cmd_sub_op_names[cmd_op_misc2 >> 4] = cmd_misc2_op_names; - cmd_op_names[cmd_op_segment >> 4] = "(segment)"; - cmd_sub_op_names[cmd_op_segment >> 4] = cmd_segment_op_names; - cmd_op_names[cmd_op_path >> 4] = "(path)"; - cmd_sub_op_names[cmd_op_path >> 4] = cmd_path_op_names; + cmd_op_names[cmd_op_misc2 >> 4] = "(misc2)"; + cmd_sub_op_names[cmd_op_misc2 >> 4] = cmd_misc2_op_names; + cmd_op_names[cmd_op_segment >> 4] = "(segment)"; + cmd_sub_op_names[cmd_op_segment >> 4] = cmd_segment_op_names; + cmd_op_names[cmd_op_path >> 4] = "(path)"; + cmd_sub_op_names[cmd_op_path >> 4] = cmd_path_op_names; #endif - gs_clist_device_procs.fill_path = clist_fill_path; - gs_clist_device_procs.stroke_path = clist_stroke_path; - cmd_opvar_disable_clip = cmd_opv_disable_clip; - cmd_opvar_enable_clip = cmd_opv_enable_clip; + gs_clist_device_procs.fill_path = clist_fill_path; + gs_clist_device_procs.stroke_path = clist_stroke_path; + cmd_opvar_disable_clip = cmd_opv_disable_clip; + cmd_opvar_enable_clip = cmd_opv_enable_clip; } /* ------ Utilities ------ */ @@ -79,682 +85,702 @@ gs_clpath_init(gs_memory_t *mem) /* We should be able to share this with clist_tile_rectangle, */ /* but I don't see how to do it without adding a level of procedure. */ int -cmd_put_drawing_color(gx_device_clist_writer *cldev, gx_clist_state *pcls, - const gx_drawing_color *pdcolor) -{ const gx_strip_bitmap *tile; - gx_color_index color0, color1; - ulong offset_temp; - - if ( gx_dc_is_pure(pdcolor) ) - { gx_color_index color1 = gx_dc_pure_color(pdcolor); - if ( color1 != pcls->colors[1] ) - { int code = cmd_set_color1(cldev, pcls, color1); - if ( code < 0 ) - return code; - } +cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls, + const gx_drawing_color * pdcolor) +{ + const gx_strip_bitmap *tile; + gx_color_index color0, color1; + ulong offset_temp; + + if (gx_dc_is_pure(pdcolor)) { + gx_color_index color1 = gx_dc_pure_color(pdcolor); + + if (color1 != pcls->colors[1]) { + int code = cmd_set_color1(cldev, pcls, color1); + + if (code < 0) + return code; + } #ifdef FUTURE - return cmd_dc_type_pure; + return cmd_dc_type_pure; #else - return 0; + return 0; #endif - } + } #ifdef FUTURE - /* Any non-pure color will require the phase. */ - { int px = pdcolor->phase.x, py = pdcolor->phase.y; - if ( px != pcls->tile_phase.x || py != pcls->tile_phase.y ) - { int code = cmd_set_tile_phase(cldev, pcls, px, py); - if ( code < 0 ) - return code; - } + /* Any non-pure color will require the phase. */ + { + int px = pdcolor->phase.x, py = pdcolor->phase.y; + + if (px != pcls->tile_phase.x || py != pcls->tile_phase.y) { + int code = cmd_set_tile_phase(cldev, pcls, px, py); + + if (code < 0) + return code; } + } #endif - if ( gx_dc_is_binary_halftone(pdcolor) ) - { tile = gx_dc_binary_tile(pdcolor); - color0 = gx_dc_binary_color0(pdcolor); - color1 = gx_dc_binary_color1(pdcolor); - /* Set up tile and colors as for clist_tile_rectangle. */ - if ( !cls_has_tile_id(cldev, pcls, tile->id, offset_temp) ) - { int depth = - (color1 == gx_no_color_index && - color0 == gx_no_color_index ? - cldev->color_info.depth : 1); - if ( tile->id == gx_no_bitmap_id || - clist_change_tile(cldev, pcls, tile, depth) < 0 - ) - return_error(-1); /* can't cache tile */ - } - if ( color1 != pcls->tile_colors[1] || - color0 != pcls->tile_colors[0] - ) - { int code = cmd_set_tile_colors(cldev, pcls, color0, color1); - if ( code < 0 ) - return code; - } + if (gx_dc_is_binary_halftone(pdcolor)) { + tile = gx_dc_binary_tile(pdcolor); + color0 = gx_dc_binary_color0(pdcolor); + color1 = gx_dc_binary_color1(pdcolor); + /* Set up tile and colors as for clist_tile_rectangle. */ + if (!cls_has_tile_id(cldev, pcls, tile->id, offset_temp)) { + int depth = + (color1 == gx_no_color_index && + color0 == gx_no_color_index ? + cldev->color_info.depth : 1); + + if (tile->id == gx_no_bitmap_id || + clist_change_tile(cldev, pcls, tile, depth) < 0 + ) + return_error(-1); /* can't cache tile */ + } + if (color1 != pcls->tile_colors[1] || + color0 != pcls->tile_colors[0] + ) { + int code = cmd_set_tile_colors(cldev, pcls, color0, color1); + + if (code < 0) + return code; + } #ifdef FUTURE - return cmd_dc_type_ht; + return cmd_dc_type_ht; #endif - } + } #ifdef FUTURE - else if ( gx_dc_is_colored_halftone(pdcolor) ) - { const gx_device_halftone *pdht = pdcolor->colors.colored.c_ht; - int num_comp = pdht->num_comp; - byte buf[4 + 4 * cmd_max_intsize(sizeof(pdcolor->colors.colored.c_level[0]))]; - byte *bp = buf; - int i; - uint short_bases = 0; - ulong bases = 0; - byte *dp; - int code; - - /****** HOW TO TELL IF COLOR IS ALREADY SET? ******/ - if ( pdht->id != cldev->device_halftone_id ) - { int code = cmd_put_halftone(cldev, pdht, pdht->type); - if ( code < 0 ) - return code; - cldev->device_halftone_id = pdht->id; - } - for ( i = 0; i < num_comp; ++i ) - { uint base = pdcolor->colors.colored.c_base[i]; - if ( base > 31 ) - return_error(gs_error_rangecheck); - bases |= base << ((3 - i) * 5); - short_bases |= base << (3 - i); - } - if ( bases & 0xf7bde ) - { /* Some base value requires more than 1 bit. */ - *bp++ = 0x10 + (byte)(bases >> 16); - *bp++ = (byte)(bases >> 8); - *bp++ = (byte)bases; - } - else - { /* The bases all fit in 1 bit each. */ - *bp++ = 0x00 + (byte)short_bases; - } - for ( i = 0; i < num_comp; ++i ) - bp = cmd_put_w((uint)pdcolor->colors.colored.c_level[i], bp); - /****** IGNORE alpha ******/ - code = - set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_color, bp - buf + 1); + else if (gx_dc_is_colored_halftone(pdcolor)) { + const gx_device_halftone *pdht = pdcolor->colors.colored.c_ht; + int num_comp = pdht->num_comp; + byte buf[4 + 4 * cmd_max_intsize(sizeof(pdcolor->colors.colored.c_level[0]))]; + byte *bp = buf; + int i; + uint short_bases = 0; + ulong bases = 0; + byte *dp; + int code; + +/****** HOW TO TELL IF COLOR IS ALREADY SET? ******/ + if (pdht->id != cldev->device_halftone_id) { + int code = cmd_put_halftone(cldev, pdht, pdht->type); + if (code < 0) - return code; - memcpy(dp + 1, buf, bp - buf); - return cmd_dc_type_color; - } + return code; + cldev->device_halftone_id = pdht->id; + } + for (i = 0; i < num_comp; ++i) { + uint base = pdcolor->colors.colored.c_base[i]; + + if (base > 31) + return_error(gs_error_rangecheck); + bases |= base << ((3 - i) * 5); + short_bases |= base << (3 - i); + } + if (bases & 0xf7bde) { /* Some base value requires more than 1 bit. */ + *bp++ = 0x10 + (byte) (bases >> 16); + *bp++ = (byte) (bases >> 8); + *bp++ = (byte) bases; + } else { /* The bases all fit in 1 bit each. */ + *bp++ = 0x00 + (byte) short_bases; + } + for (i = 0; i < num_comp; ++i) + bp = cmd_put_w((uint) pdcolor->colors.colored.c_level[i], bp); +/****** IGNORE alpha ******/ + code = + set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_color, bp - buf + 1); + if (code < 0) + return code; + memcpy(dp + 1, buf, bp - buf); + return cmd_dc_type_color; + } #endif - else - return_error(-1); + else + return_error(-1); #ifndef FUTURE - { int px = pdcolor->phase.x, py = pdcolor->phase.y; - if ( px != pcls->tile_phase.x || py != pcls->tile_phase.y ) - { int code = cmd_set_tile_phase(cldev, pcls, px, py); - if ( code < 0 ) - return code; - } + { + int px = pdcolor->phase.x, py = pdcolor->phase.y; + + if (px != pcls->tile_phase.x || py != pcls->tile_phase.y) { + int code = cmd_set_tile_phase(cldev, pcls, px, py); + + if (code < 0) + return code; } + } #endif - return 0; + return 0; } /* Clear (a) specific 'known' flag(s) for all bands. */ /* We must do this whenever the value of a 'known' parameter changes. */ void -cmd_clear_known(gx_device_clist_writer *cldev, uint known) -{ ushort unknown = ~known; - gx_clist_state *pcls = cldev->states; - int i; +cmd_clear_known(gx_device_clist_writer * cldev, uint known) +{ + ushort unknown = ~known; + gx_clist_state *pcls = cldev->states; + int i; - for ( i = cldev->nbands; --i >= 0; ++pcls ) - pcls->known &= unknown; + for (i = cldev->nbands; --i >= 0; ++pcls) + pcls->known &= unknown; } /* Check whether we need to change the clipping path in the device. */ bool -cmd_check_clip_path(gx_device_clist_writer *cldev, const gx_clip_path *pcpath) -{ if ( pcpath == NULL ) - return false; - /* The clip path might have moved in memory, so even if the */ - /* ids match, update the pointer. */ - cldev->clip_path = pcpath; - if ( pcpath->id == cldev->clip_path_id ) - return false; - cldev->clip_path_id = pcpath->id; - return true; +cmd_check_clip_path(gx_device_clist_writer * cldev, const gx_clip_path * pcpath) +{ + if (pcpath == NULL) + return false; + /* The clip path might have moved in memory, so even if the */ + /* ids match, update the pointer. */ + cldev->clip_path = pcpath; + if (pcpath->id == cldev->clip_path_id) + return false; + cldev->clip_path_id = pcpath->id; + return true; } /* Construct the parameters for writing out a matrix. */ /* We need a buffer of at least 1 + 6 * sizeof(float) bytes. */ byte * -cmd_for_matrix(byte *cbuf, const gs_matrix *pmat) -{ byte *cp = cbuf + 1; - byte b = 0; - float coeffs[6]; - int i; - - coeffs[0] = pmat->xx; - coeffs[1] = pmat->xy; - coeffs[2] = pmat->yx; - coeffs[3] = pmat->yy; - coeffs[4] = pmat->tx; - coeffs[5] = pmat->ty; - for ( i = 0; i < 4; i += 2 ) - { float u = coeffs[i], v = coeffs[i^3]; - b <<= 2; - if ( u != 0 || v != 0 ) - { memcpy(cp, &u, sizeof(float)); - cp += sizeof(float); - if ( v == u ) - b += 1; - else if ( v == -u ) - b += 2; - else - { b += 3; - memcpy(cp, &v, sizeof(float)); - cp += sizeof(float); - } - } - } - for ( ; i < 6; ++i ) - { float v = coeffs[i]; - b <<= 1; - if ( v != 0 ) - { ++b; - memcpy(cp, &v, sizeof(float)); - cp += sizeof(float); - } - } - cbuf[0] = b << 2; - return cp; +cmd_for_matrix(byte * cbuf, const gs_matrix * pmat) +{ + byte *cp = cbuf + 1; + byte b = 0; + float coeffs[6]; + int i; + + coeffs[0] = pmat->xx; + coeffs[1] = pmat->xy; + coeffs[2] = pmat->yx; + coeffs[3] = pmat->yy; + coeffs[4] = pmat->tx; + coeffs[5] = pmat->ty; + for (i = 0; i < 4; i += 2) { + float u = coeffs[i], v = coeffs[i ^ 3]; + + b <<= 2; + if (u != 0 || v != 0) { + memcpy(cp, &u, sizeof(float)); + cp += sizeof(float); + + if (v == u) + b += 1; + else if (v == -u) + b += 2; + else { + b += 3; + memcpy(cp, &v, sizeof(float)); + cp += sizeof(float); + } + } + } + for (; i < 6; ++i) { + float v = coeffs[i]; + + b <<= 1; + if (v != 0) { + ++b; + memcpy(cp, &v, sizeof(float)); + cp += sizeof(float); + } + } + cbuf[0] = b << 2; + return cp; } /* Write out values of any unknown parameters. */ int -cmd_write_unknown(gx_device_clist_writer *cldev, gx_clist_state *pcls, - uint must_know) -{ int code; - ushort unknown = ~pcls->known & must_know; - - if ( unknown & flatness_known ) - { byte *dp; - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_flatness, - 1 + sizeof(float)); - if (code < 0) - return code; - memcpy(dp + 1, &cldev->imager_state.flatness, sizeof(float)); - pcls->known |= flatness_known; - } - if ( unknown & fill_adjust_known ) - { byte *dp; - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_fill_adjust, - 1 + sizeof(fixed) * 2); - if (code < 0) - return code; - memcpy(dp + 1, &cldev->imager_state.fill_adjust.x, sizeof(fixed)); - memcpy(dp + 1 + sizeof(fixed), &cldev->imager_state.fill_adjust.y, sizeof(fixed)); - pcls->known |= fill_adjust_known; - } - if ( unknown & ctm_known ) - { byte cbuf[1 + 6 * sizeof(float)]; - uint len = - cmd_for_matrix(cbuf, - (const gs_matrix *)&cldev->imager_state.ctm) - - cbuf; - byte *dp; - - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_ctm, len + 1); - if (code < 0) - return code; - memcpy(dp + 1, cbuf, len); - pcls->known |= ctm_known; - } - if ( unknown & line_width_known ) - { byte *dp; - float width = - gx_current_line_width(&cldev->imager_state.line_params); - - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_line_width, - 1 + sizeof(width)); - if (code < 0) - return code; - memcpy(dp + 1, &width, sizeof(width)); - pcls->known |= line_width_known; - } - if ( unknown & miter_limit_known ) - { byte *dp; - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_miter_limit, - 1 + sizeof(float)); - if (code < 0) - return code; - memcpy(dp + 1, &cldev->imager_state.line_params.miter_limit, sizeof(float)); - pcls->known |= miter_limit_known; - } - if ( unknown & misc0_known ) - { byte *dp; - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_misc2, 2); - if (code < 0) - return code; - dp[1] = cmd_set_misc2_cap_join + - (cldev->imager_state.line_params.cap << 3) + - cldev->imager_state.line_params.join; - pcls->known |= misc0_known; - } - if ( unknown & misc1_known ) - { byte *dp; - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_misc2, 2); - if (code < 0) - return code; - dp[1] = cmd_set_misc2_ac_op_sa + - (cldev->imager_state.accurate_curves ? 4 : 0) + - (cldev->imager_state.overprint ? 2 : 0) + - (cldev->imager_state.stroke_adjust ? 1 : 0); - pcls->known |= misc1_known; - } - if ( unknown & dash_known ) - { byte *dp; - int n = cldev->imager_state.line_params.dash.pattern_size; - - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_dash, - 2 + (n + 2) * sizeof(float)); - if (code < 0) - return code; - dp[1] = n + (cldev->imager_state.line_params.dash.adapt ? 0x80 : 0) + - (cldev->imager_state.line_params.dot_length_absolute ? 0x40 : 0); - memcpy(dp + 2, &cldev->imager_state.line_params.dot_length, - sizeof(float)); - memcpy(dp + 2 + sizeof(float), - &cldev->imager_state.line_params.dash.offset, - sizeof(float)); - if ( n != 0 ) - memcpy(dp + 2 + sizeof(float) * 2, - cldev->imager_state.line_params.dash.pattern, - n * sizeof(float)); - pcls->known |= dash_known; - } - if ( unknown & clip_path_known ) - { /* We can write out the clipping path either as rectangles */ - /* or as a real (filled) path. */ - const gx_clip_path *pcpath = cldev->clip_path; - int band_height = cldev->page_band_height; - int ymin = (pcls - cldev->states) * band_height; - int ymax = min(ymin + band_height, cldev->height); - gs_fixed_rect box; - int punt_to_outer_box = 0; - byte *dp; - int code; - int end_code; +cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls, + uint must_know) +{ + int code; + ushort unknown = ~pcls->known & must_know; - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_begin_clip, 1); - if (code < 0) - return code; - if (pcpath->segments_valid) - { - if ( gx_path_is_rectangle(&pcpath->path, &box) && - fixed_is_int(box.p.x | box.p.y | box.q.x | box.q.y) - ) - { /* Write the path as a rectangle. */ - code = cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect, - fixed2int_var(box.p.x), - fixed2int_var(box.p.y), - fixed2int(box.q.x - box.p.x), - fixed2int(box.q.y - box.p.y)); - } - else if ( !(cldev->disable_mask & clist_disable_complex_clip) ) - { /* Write the path. */ - code = cmd_put_path(cldev, pcls, &pcpath->path, - int2fixed(ymin - 1), - int2fixed(ymax + 1), - (pcpath->rule == gx_rule_even_odd ? - cmd_opv_eofill : cmd_opv_fill), - true, sn_not_first); - } - else - /* Complex paths disabled: write outer box as clip */ - punt_to_outer_box = 1; - } - else - { /* Write out the rectangles. */ - const gx_clip_rect *prect = pcpath->list.head; - - if ( prect == 0 ) - prect = &pcpath->list.single; - else if (cldev->disable_mask & clist_disable_complex_clip) - punt_to_outer_box = 1; - if (!punt_to_outer_box) - for ( ; prect != 0 && code >= 0; prect = prect->next ) - if ( prect->xmax > prect->xmin && - prect->ymin < ymax && prect->ymax > ymin - ) - { code = - cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect, - prect->xmin, prect->ymin, - prect->xmax - prect->xmin, - prect->ymax - prect->ymin); - } - } - if (punt_to_outer_box) - { /* Clip is complex, but disabled. Write out the outer box */ - gs_fixed_rect box; - gx_cpath_outer_box(pcpath, &box); - box.p.x = fixed_floor(box.p.x); - box.p.y = fixed_floor(box.p.y); + if (unknown & flatness_known) { + byte *dp; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_flatness, + 1 + sizeof(float)); + + if (code < 0) + return code; + memcpy(dp + 1, &cldev->imager_state.flatness, sizeof(float)); + + pcls->known |= flatness_known; + } + if (unknown & fill_adjust_known) { + byte *dp; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_fill_adjust, + 1 + sizeof(fixed) * 2); + if (code < 0) + return code; + memcpy(dp + 1, &cldev->imager_state.fill_adjust.x, sizeof(fixed)); + memcpy(dp + 1 + sizeof(fixed), &cldev->imager_state.fill_adjust.y, sizeof(fixed)); + pcls->known |= fill_adjust_known; + } + if (unknown & ctm_known) { + byte cbuf[1 + 6 * sizeof(float)]; + uint len = + cmd_for_matrix(cbuf, + (const gs_matrix *)&cldev->imager_state.ctm) - + cbuf; + byte *dp; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_ctm, len + 1); + if (code < 0) + return code; + memcpy(dp + 1, cbuf, len); + pcls->known |= ctm_known; + } + if (unknown & line_width_known) { + byte *dp; + float width = + gx_current_line_width(&cldev->imager_state.line_params); + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_line_width, + 1 + sizeof(width)); + if (code < 0) + return code; + memcpy(dp + 1, &width, sizeof(width)); + pcls->known |= line_width_known; + } + if (unknown & miter_limit_known) { + byte *dp; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_miter_limit, + 1 + sizeof(float)); + + if (code < 0) + return code; + memcpy(dp + 1, &cldev->imager_state.line_params.miter_limit, sizeof(float)); + + pcls->known |= miter_limit_known; + } + if (unknown & misc0_known) { + byte *dp; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_misc2, 2); + if (code < 0) + return code; + dp[1] = cmd_set_misc2_cap_join + + (cldev->imager_state.line_params.cap << 3) + + cldev->imager_state.line_params.join; + pcls->known |= misc0_known; + } + if (unknown & misc1_known) { + byte *dp; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_misc2, 2); + if (code < 0) + return code; + dp[1] = cmd_set_misc2_ac_op_sa + + (cldev->imager_state.accurate_curves ? 4 : 0) + + (cldev->imager_state.overprint ? 2 : 0) + + (cldev->imager_state.stroke_adjust ? 1 : 0); + pcls->known |= misc1_known; + } + if (unknown & dash_known) { + byte *dp; + int n = cldev->imager_state.line_params.dash.pattern_size; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_dash, + 2 + (n + 2) * sizeof(float)); + + if (code < 0) + return code; + dp[1] = n + (cldev->imager_state.line_params.dash.adapt ? 0x80 : 0) + + (cldev->imager_state.line_params.dot_length_absolute ? 0x40 : 0); + memcpy(dp + 2, &cldev->imager_state.line_params.dot_length, + sizeof(float)); + memcpy(dp + 2 + sizeof(float), + &cldev->imager_state.line_params.dash.offset, + sizeof(float)); + + if (n != 0) + memcpy(dp + 2 + sizeof(float) * 2, + cldev->imager_state.line_params.dash.pattern, + n * sizeof(float)); + + pcls->known |= dash_known; + } + if (unknown & clip_path_known) { /* We can write out the clipping path either as rectangles */ + /* or as a real (filled) path. */ + const gx_clip_path *pcpath = cldev->clip_path; + int band_height = cldev->page_band_height; + int ymin = (pcls - cldev->states) * band_height; + int ymax = min(ymin + band_height, cldev->height); + gs_fixed_rect box; + int punt_to_outer_box = 0; + byte *dp; + int code; + int end_code; + + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_begin_clip, 1); + if (code < 0) + return code; + if (pcpath->segments_valid) { + if (gx_path_is_rectangle(&pcpath->path, &box) && + fixed_is_int(box.p.x | box.p.y | box.q.x | box.q.y) + ) { /* Write the path as a rectangle. */ code = cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect, fixed2int_var(box.p.x), fixed2int_var(box.p.y), - fixed2int_ceiling(box.q.x - box.p.x), - fixed2int_ceiling(box.q.y - box.p.y)); - } - end_code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_end_clip, 2); - if (code >= 0) - code = end_code; /* take the first failure seen */ - if (end_code < 0 && cldev->error_is_retryable) - { /* end_clip has to work despite lo-mem to maintain consistency. */ - /* This isn't error recovery, but just to prevent dangling */ - /* cmd_opv_begin_clip's */ - ++cldev->ignore_lo_mem_warnings; - end_code - = set_cmd_put_op(dp, cldev, pcls, cmd_opv_end_clip, 2); - --cldev->ignore_lo_mem_warnings; - } - if (end_code >= 0) - dp[1] = (gx_cpath_is_outside(pcpath) ? 1 : 0); + fixed2int(box.q.x - box.p.x), + fixed2int(box.q.y - box.p.y)); + } else if (!(cldev->disable_mask & clist_disable_complex_clip)) { /* Write the path. */ + code = cmd_put_path(cldev, pcls, &pcpath->path, + int2fixed(ymin - 1), + int2fixed(ymax + 1), + (pcpath->rule == gx_rule_even_odd ? + cmd_opv_eofill : cmd_opv_fill), + true, sn_not_first); + } else + /* Complex paths disabled: write outer box as clip */ + punt_to_outer_box = 1; + } else { /* Write out the rectangles. */ + const gx_clip_rect *prect = pcpath->list.head; + + if (prect == 0) + prect = &pcpath->list.single; + else if (cldev->disable_mask & clist_disable_complex_clip) + punt_to_outer_box = 1; + if (!punt_to_outer_box) + for (; prect != 0 && code >= 0; prect = prect->next) + if (prect->xmax > prect->xmin && + prect->ymin < ymax && prect->ymax > ymin + ) { + code = + cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect, + prect->xmin, prect->ymin, + prect->xmax - prect->xmin, + prect->ymax - prect->ymin); + } + } + if (punt_to_outer_box) { /* Clip is complex, but disabled. Write out the outer box */ + gs_fixed_rect box; + + gx_cpath_outer_box(pcpath, &box); + box.p.x = fixed_floor(box.p.x); + box.p.y = fixed_floor(box.p.y); + code = cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect, + fixed2int_var(box.p.x), + fixed2int_var(box.p.y), + fixed2int_ceiling(box.q.x - box.p.x), + fixed2int_ceiling(box.q.y - box.p.y)); + } + end_code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_end_clip, 2); + if (code >= 0) + code = end_code; /* take the first failure seen */ + if (end_code < 0 && cldev->error_is_retryable) { /* end_clip has to work despite lo-mem to maintain consistency. */ + /* This isn't error recovery, but just to prevent dangling */ + /* cmd_opv_begin_clip's */ + ++cldev->ignore_lo_mem_warnings; + end_code + = set_cmd_put_op(dp, cldev, pcls, cmd_opv_end_clip, 2); + --cldev->ignore_lo_mem_warnings; + } + if (end_code >= 0) + dp[1] = (gx_cpath_is_outside(pcpath) ? 1 : 0); + if (code < 0) + return code; + pcls->clip_enabled = 1; + pcls->known |= clip_path_known; + } + if (unknown & color_space_known) { + byte *dp; + + if (cldev->color_space & 8) { /* indexed */ + uint num_values = (cldev->indexed_params.hival + 1) * + gs_color_space_num_components( + (const gs_color_space *)&cldev->indexed_params.base_space); + bool use_proc = cldev->color_space & 4; + const void *map_data; + uint map_size; + + if (use_proc) { + map_data = cldev->indexed_params.lookup.map->values; + map_size = num_values * + sizeof(cldev->indexed_params.lookup.map->values[0]); + } else { + map_data = cldev->indexed_params.lookup.table.data; + map_size = num_values; + } + code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_color_space, + 2 + cmd_sizew(cldev->indexed_params.hival) + map_size); if (code < 0) - return code; - pcls->clip_enabled = 1; - pcls->known |= clip_path_known; - } - if ( unknown & color_space_known ) - { byte *dp; - - if ( cldev->color_space & 8 ) /* indexed */ - { uint num_values = (cldev->indexed_params.hival + 1) * - gs_color_space_num_components( - (const gs_color_space *)&cldev->indexed_params.base_space); - bool use_proc = cldev->color_space & 4; - const void *map_data; - uint map_size; - - if ( use_proc ) - { map_data = cldev->indexed_params.lookup.map->values; - map_size = num_values * - sizeof(cldev->indexed_params.lookup.map->values[0]); - } - else - { map_data = cldev->indexed_params.lookup.table.data; - map_size = num_values; - } - code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_color_space, - 2 + cmd_sizew(cldev->indexed_params.hival) + map_size); + return code; + memcpy(cmd_put_w(cldev->indexed_params.hival, dp + 2), + map_data, map_size); + } else { + code = + set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_color_space, 2); if (code < 0) - return code; - memcpy(cmd_put_w(cldev->indexed_params.hival, dp + 2), - map_data, map_size); - } - else - { code = - set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_color_space, 2); - if (code < 0) - return code; - } - dp[1] = cldev->color_space; - pcls->known |= color_space_known; - } - return 0; -} + return code; + } + dp[1] = cldev->color_space; + pcls->known |= color_space_known; + } + return 0; +} /* ------ Driver procedures ------ */ private int -clist_fill_path(gx_device *dev, const gs_imager_state *pis, gx_path *ppath, - const gx_fill_params *params, const gx_drawing_color *pdcolor, - const gx_clip_path *pcpath) -{ uint unknown = 0; - int y, height, y0, y1; - gs_logical_operation_t lop = pis->log_op; - byte op = (byte) - (params->rule == gx_rule_even_odd ? +clist_fill_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath, + const gx_fill_params * params, const gx_drawing_color * pdcolor, + const gx_clip_path * pcpath) +{ + uint unknown = 0; + int y, height, y0, y1; + gs_logical_operation_t lop = pis->log_op; + byte op = (byte) + (params->rule == gx_rule_even_odd ? #ifdef FUTURE - cmd_opv_eofill : cmd_opv_fill + cmd_opv_eofill : cmd_opv_fill #else - (gx_dc_is_pure(pdcolor) ? cmd_opv_eofill : cmd_opv_hteofill) : - (gx_dc_is_pure(pdcolor) ? cmd_opv_fill : cmd_opv_htfill) + (gx_dc_is_pure(pdcolor) ? cmd_opv_eofill : cmd_opv_hteofill): + (gx_dc_is_pure(pdcolor) ? cmd_opv_fill : cmd_opv_htfill) #endif - ); - gs_fixed_point adjust; + ); + gs_fixed_point adjust; - if ( (cdev->disable_mask & clist_disable_fill_path) - || gs_debug_c(',') /* disable path-based banding */ - ) - return gx_default_fill_path(dev, pis, ppath, params, pdcolor, - pcpath); - adjust = params->adjust; - { gs_fixed_rect bbox; - gx_path_bbox(ppath, &bbox); - y = fixed2int(bbox.p.y) - 1; - height = fixed2int_ceiling(bbox.q.y) - y + 1; - fit_fill_yh(dev, y, height); - if ( height <= 0 ) + if ((cdev->disable_mask & clist_disable_fill_path) + || gs_debug_c(',') /* disable path-based banding */ + ) + return gx_default_fill_path(dev, pis, ppath, params, pdcolor, + pcpath); + adjust = params->adjust; + { + gs_fixed_rect bbox; + + gx_path_bbox(ppath, &bbox); + y = fixed2int(bbox.p.y) - 1; + height = fixed2int_ceiling(bbox.q.y) - y + 1; + fit_fill_yh(dev, y, height); + if (height <= 0) return 0; - } - y0 = y; - y1 = y + height; - if ( cdev->imager_state.flatness != params->flatness ) - { unknown |= flatness_known; - cdev->imager_state.flatness = params->flatness; - } - if ( cdev->imager_state.fill_adjust.x != adjust.x || - cdev->imager_state.fill_adjust.y != adjust.y - ) - { unknown |= fill_adjust_known; - cdev->imager_state.fill_adjust = adjust; - } - if ( cmd_check_clip_path(cdev, pcpath) ) - unknown |= clip_path_known; - if ( unknown ) - cmd_clear_known(cdev, unknown); - BEGIN_RECT + } + y0 = y; + y1 = y + height; + if (cdev->imager_state.flatness != params->flatness) { + unknown |= flatness_known; + cdev->imager_state.flatness = params->flatness; + } + if (cdev->imager_state.fill_adjust.x != adjust.x || + cdev->imager_state.fill_adjust.y != adjust.y + ) { + unknown |= fill_adjust_known; + cdev->imager_state.fill_adjust = adjust; + } + if (cmd_check_clip_path(cdev, pcpath)) + unknown |= clip_path_known; + if (unknown) + cmd_clear_known(cdev, unknown); + BEGIN_RECT int code = cmd_do_write_unknown(cdev, pcls, - flatness_known | fill_adjust_known | - clip_path_known); - if (code < 0) - return code; - if ( ( code = cmd_do_enable_clip(cdev, pcls, pcpath != NULL) ) < 0 ) - return code; - if ( lop == lop_default ) - { if ( ( code = cmd_disable_lop(cdev, pcls) ) < 0 ) - return code; - } - else - { if ( lop != pcls->lop ) - { code = cmd_set_lop(cdev, pcls, lop); - if ( code < 0 ) - return code; - } - if ( ( code = cmd_enable_lop(cdev, pcls) ) < 0 ) - return code; - } - code = cmd_put_drawing_color(cdev, pcls, pdcolor); - if ( code < 0 ) - { /* Something went wrong, use the default implementation. */ - return gx_default_fill_path(dev, pis, ppath, params, pdcolor, - pcpath); - } - code = cmd_put_path(cdev, pcls, ppath, - int2fixed(max(y - 1, y0)), - int2fixed(min(y + height + 1, y1)), + flatness_known | fill_adjust_known | + clip_path_known); + + if (code < 0) + return code; + if ((code = cmd_do_enable_clip(cdev, pcls, pcpath != NULL)) < 0) + return code; + if (lop == lop_default) { + if ((code = cmd_disable_lop(cdev, pcls)) < 0) + return code; + } else { + if (lop != pcls->lop) { + code = cmd_set_lop(cdev, pcls, lop); + if (code < 0) + return code; + } + if ((code = cmd_enable_lop(cdev, pcls)) < 0) + return code; + } + code = cmd_put_drawing_color(cdev, pcls, pdcolor); + if (code < 0) { /* Something went wrong, use the default implementation. */ + return gx_default_fill_path(dev, pis, ppath, params, pdcolor, + pcpath); + } + code = cmd_put_path(cdev, pcls, ppath, + int2fixed(max(y - 1, y0)), + int2fixed(min(y + height + 1, y1)), #ifdef FUTURE - op + code, /* cmd_dc_type */ + op + code, /* cmd_dc_type */ #else - op, + op, #endif - true, sn_none /* fill doesn't need the notes */); - if ( code < 0 ) - return code; - END_RECT + true, sn_none /* fill doesn't need the notes */ ); + if (code < 0) + return code; + END_RECT return 0; } private int -clist_stroke_path(gx_device *dev, const gs_imager_state *pis, gx_path *ppath, - const gx_stroke_params *params, - const gx_drawing_color *pdcolor, const gx_clip_path *pcpath) -{ int pattern_size = pis->line_params.dash.pattern_size; - uint unknown = 0; - gs_fixed_rect bbox; - gs_fixed_point expansion; - int adjust_y; - int y, height, y0, y1; - gs_logical_operation_t lop = pis->log_op; +clist_stroke_path(gx_device * dev, const gs_imager_state * pis, gx_path * ppath, + const gx_stroke_params * params, + const gx_drawing_color * pdcolor, const gx_clip_path * pcpath) +{ + int pattern_size = pis->line_params.dash.pattern_size; + uint unknown = 0; + gs_fixed_rect bbox; + gs_fixed_point expansion; + int adjust_y; + int y, height, y0, y1; + gs_logical_operation_t lop = pis->log_op; + #ifndef FUTURE - byte op = (byte) - (gx_dc_is_pure(pdcolor) ? cmd_opv_stroke : cmd_opv_htstroke); + byte op = (byte) + (gx_dc_is_pure(pdcolor) ? cmd_opv_stroke : cmd_opv_htstroke); + #endif - if ( (cdev->disable_mask & clist_disable_stroke_path) - || gs_debug_c(',') /* disable path-based banding */ - ) - return gx_default_stroke_path(dev, pis, ppath, params, pdcolor, - pcpath); - gx_path_bbox(ppath, &bbox); - /* We must use the supplied imager state, not our saved one, */ - /* for computing the stroke expansion. */ - if ( gx_stroke_path_expansion(pis, ppath, &expansion) < 0 ) - { /* Expansion is too large: use the entire page. */ - adjust_y = 0; - y = 0; - height = dev->height; - } - else - { adjust_y = fixed2int_ceiling(expansion.y) + 1; - y = fixed2int(bbox.p.y) - adjust_y; - height = fixed2int_ceiling(bbox.q.y) - y + adjust_y; - fit_fill_yh(dev, y, height); - if ( height <= 0 ) - return 0; - } - y0 = y; - y1 = y + height; - /* Check the dash pattern, since we bail out if */ - /* the pattern is too large. */ - cdev->imager_state.line_params.dash.pattern = cdev->dash_pattern; - if ( cdev->imager_state.line_params.dash.pattern_size != pattern_size || - (pattern_size != 0 && - memcmp(cdev->imager_state.line_params.dash.pattern, - pis->line_params.dash.pattern, - pattern_size * sizeof(float))) || - cdev->imager_state.line_params.dash.offset != - pis->line_params.dash.offset || - cdev->imager_state.line_params.dash.adapt != - pis->line_params.dash.adapt || - cdev->imager_state.line_params.dot_length != - pis->line_params.dot_length || - cdev->imager_state.line_params.dot_length_absolute != - pis->line_params.dot_length_absolute - ) - { /* Bail out if the dash pattern is too long. */ - if ( pattern_size > cmd_max_dash ) - return gx_default_stroke_path(dev, pis, ppath, params, - pdcolor, pcpath); - unknown |= dash_known; - gx_set_dash(&cdev->imager_state.line_params.dash, - pis->line_params.dash.pattern, - pis->line_params.dash.pattern_size, - pis->line_params.dash.offset, NULL); - gx_set_dash_adapt(&cdev->imager_state.line_params.dash, - pis->line_params.dash.adapt); - gx_set_dot_length(&cdev->imager_state.line_params, - pis->line_params.dot_length, - pis->line_params.dot_length_absolute); - } - if ( state_neq(flatness) ) - { unknown |= flatness_known; - state_update(flatness); - } - if ( state_neq(fill_adjust.x) || state_neq(fill_adjust.y) ) - { unknown |= fill_adjust_known; - state_update(fill_adjust); - } - if ( state_neq(ctm.xx) || state_neq(ctm.xy) || - state_neq(ctm.yx) || state_neq(ctm.yy) || - /* We don't actually need tx or ty, but we don't want to bother */ - /* tracking them separately from the other coefficients. */ - state_neq(ctm.tx) || state_neq(ctm.ty) - ) - { unknown |= ctm_known; - state_update(ctm); - } - if ( state_neq(line_params.half_width) ) - { unknown |= line_width_known; - state_update(line_params.half_width); - } - if ( state_neq(line_params.miter_limit) ) - { unknown |= miter_limit_known; - gx_set_miter_limit(&cdev->imager_state.line_params, - pis->line_params.miter_limit); - } - if ( state_neq(line_params.cap) || state_neq(line_params.join) ) - { unknown |= misc0_known; - state_update(line_params.cap); - state_update(line_params.join); - } - if ( state_neq(accurate_curves) || state_neq(overprint) || - state_neq(stroke_adjust) - ) - { unknown |= misc1_known; - state_update(accurate_curves); - state_update(overprint); - state_update(stroke_adjust); - } - if ( cmd_check_clip_path(cdev, pcpath) ) - unknown |= clip_path_known; - if ( unknown ) - cmd_clear_known(cdev, unknown); - BEGIN_RECT + if ((cdev->disable_mask & clist_disable_stroke_path) + || gs_debug_c(',') /* disable path-based banding */ + ) + return gx_default_stroke_path(dev, pis, ppath, params, pdcolor, + pcpath); + gx_path_bbox(ppath, &bbox); + /* We must use the supplied imager state, not our saved one, */ + /* for computing the stroke expansion. */ + if (gx_stroke_path_expansion(pis, ppath, &expansion) < 0) { /* Expansion is too large: use the entire page. */ + adjust_y = 0; + y = 0; + height = dev->height; + } else { + adjust_y = fixed2int_ceiling(expansion.y) + 1; + y = fixed2int(bbox.p.y) - adjust_y; + height = fixed2int_ceiling(bbox.q.y) - y + adjust_y; + fit_fill_yh(dev, y, height); + if (height <= 0) + return 0; + } + y0 = y; + y1 = y + height; + /* Check the dash pattern, since we bail out if */ + /* the pattern is too large. */ + cdev->imager_state.line_params.dash.pattern = cdev->dash_pattern; + if (cdev->imager_state.line_params.dash.pattern_size != pattern_size || + (pattern_size != 0 && + memcmp(cdev->imager_state.line_params.dash.pattern, + pis->line_params.dash.pattern, + pattern_size * sizeof(float))) || + cdev->imager_state.line_params.dash.offset != + pis->line_params.dash.offset || + cdev->imager_state.line_params.dash.adapt != + pis->line_params.dash.adapt || + cdev->imager_state.line_params.dot_length != + pis->line_params.dot_length || + cdev->imager_state.line_params.dot_length_absolute != + pis->line_params.dot_length_absolute + ) { /* Bail out if the dash pattern is too long. */ + if (pattern_size > cmd_max_dash) + return gx_default_stroke_path(dev, pis, ppath, params, + pdcolor, pcpath); + unknown |= dash_known; + gx_set_dash(&cdev->imager_state.line_params.dash, + pis->line_params.dash.pattern, + pis->line_params.dash.pattern_size, + pis->line_params.dash.offset, NULL); + gx_set_dash_adapt(&cdev->imager_state.line_params.dash, + pis->line_params.dash.adapt); + gx_set_dot_length(&cdev->imager_state.line_params, + pis->line_params.dot_length, + pis->line_params.dot_length_absolute); + } + if (state_neq(flatness)) { + unknown |= flatness_known; + state_update(flatness); + } + if (state_neq(fill_adjust.x) || state_neq(fill_adjust.y)) { + unknown |= fill_adjust_known; + state_update(fill_adjust); + } + if (state_neq(ctm.xx) || state_neq(ctm.xy) || + state_neq(ctm.yx) || state_neq(ctm.yy) || + /* We don't actually need tx or ty, but we don't want to bother */ + /* tracking them separately from the other coefficients. */ + state_neq(ctm.tx) || state_neq(ctm.ty) + ) { + unknown |= ctm_known; + state_update(ctm); + } + if (state_neq(line_params.half_width)) { + unknown |= line_width_known; + state_update(line_params.half_width); + } + if (state_neq(line_params.miter_limit)) { + unknown |= miter_limit_known; + gx_set_miter_limit(&cdev->imager_state.line_params, + pis->line_params.miter_limit); + } + if (state_neq(line_params.cap) || state_neq(line_params.join)) { + unknown |= misc0_known; + state_update(line_params.cap); + state_update(line_params.join); + } + if (state_neq(accurate_curves) || state_neq(overprint) || + state_neq(stroke_adjust) + ) { + unknown |= misc1_known; + state_update(accurate_curves); + state_update(overprint); + state_update(stroke_adjust); + } + if (cmd_check_clip_path(cdev, pcpath)) + unknown |= clip_path_known; + if (unknown) + cmd_clear_known(cdev, unknown); + BEGIN_RECT int code = cmd_do_write_unknown(cdev, pcls, stroke_all_known); - if (code < 0) - return code; - if ( ( code = cmd_do_enable_clip(cdev, pcls, pcpath != NULL) ) < 0 ) - return code; - if ( lop == lop_default ) - { if ( ( code = cmd_disable_lop(cdev, pcls) ) < 0 ) - return code; - } - else - { if ( lop != pcls->lop ) - { code = cmd_set_lop(cdev, pcls, lop); - if ( code < 0 ) - return code; - } - if ( ( code = cmd_enable_lop(cdev, pcls) ) < 0 ) - return code; - } - code = cmd_put_drawing_color(cdev, pcls, pdcolor); - if ( code < 0 ) - { /* Something went wrong, use the default implementation. */ - return gx_default_stroke_path(dev, pis, ppath, params, pdcolor, - pcpath); - } - { fixed ymin, ymax; - /* If a dash pattern is active, we can't skip segments */ - /* outside the clipping region, because that would throw off */ - /* the pattern. */ - if ( pattern_size == 0 ) + + if (code < 0) + return code; + if ((code = cmd_do_enable_clip(cdev, pcls, pcpath != NULL)) < 0) + return code; + if (lop == lop_default) { + if ((code = cmd_disable_lop(cdev, pcls)) < 0) + return code; + } else { + if (lop != pcls->lop) { + code = cmd_set_lop(cdev, pcls, lop); + if (code < 0) + return code; + } + if ((code = cmd_enable_lop(cdev, pcls)) < 0) + return code; + } + code = cmd_put_drawing_color(cdev, pcls, pdcolor); + if (code < 0) { /* Something went wrong, use the default implementation. */ + return gx_default_stroke_path(dev, pis, ppath, params, pdcolor, + pcpath); + } { + fixed ymin, ymax; + + /* If a dash pattern is active, we can't skip segments */ + /* outside the clipping region, because that would throw off */ + /* the pattern. */ + if (pattern_size == 0) ymin = int2fixed(max(y - adjust_y, y0)), - ymax = int2fixed(min(y + height + adjust_y, y1)); - else + ymax = int2fixed(min(y + height + adjust_y, y1)); + else ymin = min_fixed, - ymax = max_fixed; - code = cmd_put_path(cdev, pcls, ppath, ymin, ymax, + ymax = max_fixed; + code = cmd_put_path(cdev, pcls, ppath, ymin, ymax, #ifdef FUTURE - cmd_opv_stroke + code, /* cmd_dc_type */ + cmd_opv_stroke + code, /* cmd_dc_type */ #else - op, + op, #endif - false, (segment_notes)~0); - if ( code < 0 ) + false, (segment_notes) ~ 0); + if (code < 0) return code; - } - END_RECT + } + END_RECT return 0; } @@ -762,139 +788,141 @@ clist_stroke_path(gx_device *dev, const gs_imager_state *pis, gx_path *ppath, /* Define the state bookkeeping for writing path segments. */ typedef struct cmd_segment_writer_s { - /* Set at initialization */ - gx_device_clist_writer *cldev; - gx_clist_state *pcls; - /* Updated dynamically */ - segment_notes notes; - byte *dp; - int len; - gs_fixed_point delta_first; - byte cmd[6 * (1 + sizeof(fixed))]; -} cmd_segment_writer; + /* Set at initialization */ + gx_device_clist_writer *cldev; + gx_clist_state *pcls; + /* Updated dynamically */ + segment_notes notes; + byte *dp; + int len; + gs_fixed_point delta_first; + byte cmd[6 * (1 + sizeof(fixed))]; +} +cmd_segment_writer; /* Put out a path segment command. */ private int near -cmd_put_segment(cmd_segment_writer _ss *psw, byte op, - const fixed _ss *operands, segment_notes notes) -{ const fixed _ss *optr = operands; - /* Fetch num_operands before possible command merging. */ - int i = clist_segment_op_num_operands[op & 0xf]; - byte *q = psw->cmd - 1; +cmd_put_segment(cmd_segment_writer _ss * psw, byte op, + const fixed _ss * operands, segment_notes notes) +{ + const fixed _ss *optr = operands; + + /* Fetch num_operands before possible command merging. */ + int i = clist_segment_op_num_operands[op & 0xf]; + byte *q = psw->cmd - 1; #ifdef DEBUG - if ( gs_debug_c('L') ) - { int j; - dprintf2("[L] %s:%d:", cmd_segment_op_names[op & 0xf], - (int)notes); - for ( j = 0; j < i; ++j ) - dprintf1(" %g", fixed2float(operands[j])); - dputs("\n"); - } + if (gs_debug_c('L')) { + int j; + + dprintf2("[L] %s:%d:", cmd_segment_op_names[op & 0xf], + (int)notes); + for (j = 0; j < i; ++j) + dprintf1(" %g", fixed2float(operands[j])); + dputs("\n"); + } #endif - /* Merge or shorten commands if possible. */ - if ( op == cmd_opv_rlineto ) - { if ( operands[0] == 0 ) - op = cmd_opv_vlineto, optr = ++operands, i = 1; - else if ( operands[1] == 0 ) - op = cmd_opv_hlineto, i = 1; - else - switch ( *psw->dp ) - { + /* Merge or shorten commands if possible. */ + if (op == cmd_opv_rlineto) { + if (operands[0] == 0) + op = cmd_opv_vlineto, optr = ++operands, i = 1; + else if (operands[1] == 0) + op = cmd_opv_hlineto, i = 1; + else + switch (*psw->dp) { case cmd_opv_rmoveto: - psw->delta_first.x = operands[0]; - psw->delta_first.y = operands[1]; - op = cmd_opv_rmlineto; -merge: cmd_uncount_op(*psw->dp, psw->len); - cmd_shorten_op(psw->cldev, psw->pcls, psw->len); /* delete it */ - q += psw->len - 1; - break; - case cmd_opv_rmlineto: - if ( notes != psw->notes ) + psw->delta_first.x = operands[0]; + psw->delta_first.y = operands[1]; + op = cmd_opv_rmlineto; + merge:cmd_uncount_op(*psw->dp, psw->len); + cmd_shorten_op(psw->cldev, psw->pcls, psw->len); /* delete it */ + q += psw->len - 1; break; - op = cmd_opv_rm2lineto; - goto merge; + case cmd_opv_rmlineto: + if (notes != psw->notes) + break; + op = cmd_opv_rm2lineto; + goto merge; case cmd_opv_rm2lineto: - if ( notes != psw->notes ) - break; - if ( operands[0] == -psw->delta_first.x && - operands[1] == -psw->delta_first.y - ) - { cmd_uncount_op(cmd_opv_rm2lineto, psw->len); - *psw->dp = cmd_count_op(cmd_opv_rm3lineto, psw->len); - return 0; + if (notes != psw->notes) + break; + if (operands[0] == -psw->delta_first.x && + operands[1] == -psw->delta_first.y + ) { + cmd_uncount_op(cmd_opv_rm2lineto, psw->len); + *psw->dp = cmd_count_op(cmd_opv_rm3lineto, psw->len); + return 0; } - break; + break; default: - ; - } - } - - for ( ; --i >= 0; ++optr ) - { fixed d = *optr, d2; - if ( is_bits(d, _fixed_shift + 11) && - !(d & (float2fixed(0.25) - 1)) - ) - { cmd_count_add1(cmd_diffs[3]); - d = ((d >> (_fixed_shift - 2)) & 0x1fff) + 0xc000; - q += 2; - } - else if ( is_bits(d, 19) && i > 0 && is_bits(d2 = optr[1], 19) ) - { cmd_count_add1(cmd_diffs[0]); - q[1] = (byte)((d >> 13) & 0x3f); - q[2] = (byte)(d >> 5); - q[3] = (byte)((d << 3) + ((d2 >> 16) & 7)); - q[4] = (byte)(d2 >> 8); - q[5] = (byte)d2; - q += 5; - --i, ++optr; - continue; - } - else if ( is_bits(d, 22) ) - { cmd_count_add1(cmd_diffs[1]); - q[1] = (byte)(((d >> 16) & 0x3f) + 0x40); - q += 3; - } - else if ( is_bits(d, 30) ) - { cmd_count_add1(cmd_diffs[2]); - q[1] = (byte)(((d >> 24) & 0x3f) + 0x80); - q[2] = (byte)(d >> 16); - q += 4; - } - else - { int b; - cmd_count_add1(cmd_diffs[4]); - *++q = 0xe0; - for ( b = sizeof(fixed) - 1; b > 1; --b ) - *++q = (byte)(d >> (b * 8)); - q += 2; - } - q[-1] = (byte)(d >> 8); - *q = (byte)d; - } - if ( notes != psw->notes ) - { byte *dp; - - int code = - set_cmd_put_op(dp, psw->cldev, psw->pcls, cmd_opv_set_misc2, 2); - if (code < 0) - return code; - dp[1] = cmd_set_misc2_notes + notes; - psw->notes = notes; - } - { int len = q + 2 - psw->cmd; - byte *dp; - - int code = - set_cmd_put_op(dp, psw->cldev, psw->pcls, op, len); - if (code < 0) - return code; - memcpy(dp + 1, psw->cmd, len - 1); - psw->len = len; - psw->dp = dp; + ; + } + } + for (; --i >= 0; ++optr) { + fixed d = *optr, d2; + + if (is_bits(d, _fixed_shift + 11) && + !(d & (float2fixed(0.25) - 1)) + ) { + cmd_count_add1(cmd_diffs[3]); + d = ((d >> (_fixed_shift - 2)) & 0x1fff) + 0xc000; + q += 2; + } else if (is_bits(d, 19) && i > 0 && is_bits(d2 = optr[1], 19)) { + cmd_count_add1(cmd_diffs[0]); + q[1] = (byte) ((d >> 13) & 0x3f); + q[2] = (byte) (d >> 5); + q[3] = (byte) ((d << 3) + ((d2 >> 16) & 7)); + q[4] = (byte) (d2 >> 8); + q[5] = (byte) d2; + q += 5; + --i, ++optr; + continue; + } else if (is_bits(d, 22)) { + cmd_count_add1(cmd_diffs[1]); + q[1] = (byte) (((d >> 16) & 0x3f) + 0x40); + q += 3; + } else if (is_bits(d, 30)) { + cmd_count_add1(cmd_diffs[2]); + q[1] = (byte) (((d >> 24) & 0x3f) + 0x80); + q[2] = (byte) (d >> 16); + q += 4; + } else { + int b; + + cmd_count_add1(cmd_diffs[4]); + *++q = 0xe0; + for (b = sizeof(fixed) - 1; b > 1; --b) + *++q = (byte) (d >> (b * 8)); + q += 2; } - return 0; + q[-1] = (byte) (d >> 8); + *q = (byte) d; + } + if (notes != psw->notes) { + byte *dp; + + int code = + set_cmd_put_op(dp, psw->cldev, psw->pcls, cmd_opv_set_misc2, 2); + + if (code < 0) + return code; + dp[1] = cmd_set_misc2_notes + notes; + psw->notes = notes; + } { + int len = q + 2 - psw->cmd; + byte *dp; + + int code = + set_cmd_put_op(dp, psw->cldev, psw->pcls, op, len); + + if (code < 0) + return code; + memcpy(dp + 1, psw->cmd, len - 1); + psw->len = len; + psw->dp = dp; + } + return 0; } /* Put out a line segment command. */ #define cmd_put_rmoveto(psw, operands)\ @@ -907,211 +935,219 @@ merge: cmd_uncount_op(*psw->dp, psw->len); * entirely outside the band. */ private int -cmd_put_path(gx_device_clist_writer *cldev, gx_clist_state *pcls, - const gx_path *ppath, fixed ymin, fixed ymax, byte path_op, - bool implicit_close, segment_notes keep_notes) -{ gs_path_enum cenum; - cmd_segment_writer writer; - static byte initial_op = { cmd_opv_end_run }; - /* - * We define the 'side' of a point according to its Y value as - * follows: - */ +cmd_put_path(gx_device_clist_writer * cldev, gx_clist_state * pcls, + const gx_path * ppath, fixed ymin, fixed ymax, byte path_op, + bool implicit_close, segment_notes keep_notes) +{ + gs_path_enum cenum; + cmd_segment_writer writer; + static byte initial_op = + {cmd_opv_end_run}; + + /* + * We define the 'side' of a point according to its Y value as + * follows: + */ #define which_side(y) ((y) < ymin ? -1 : (y) >= ymax ? 1 : 0) - /* - * While writing a subpath, we need to keep track of any segments - * skipped at the beginning of the subpath and any segments skipped - * just before the current segment. We do this with two sets of - * state variables, one that tracks the actual path segments and one - * that tracks the emitted segments. - * - * The following track the actual segments: - */ + /* + * While writing a subpath, we need to keep track of any segments + * skipped at the beginning of the subpath and any segments skipped + * just before the current segment. We do this with two sets of + * state variables, one that tracks the actual path segments and one + * that tracks the emitted segments. + * + * The following track the actual segments: + */ - /* - * The point and side of the last moveto (skipped if - * start_side != 0): - */ - gs_fixed_point start; - int start_side; - /* - * Whether any lines or curves were skipped immediately - * following the moveto: - */ - bool start_skip; - /* The side of the last point: */ - int side; - /* The last point with side != 0: */ - gs_fixed_point out; - /* If the last out-going segment was a lineto, */ - /* its notes: */ - segment_notes out_notes; - - /* - * The following track the emitted segments: - */ - - /* The last point emitted: */ - fixed px = int2fixed(pcls->rect.x); - fixed py = int2fixed(pcls->rect.y); - /* The point of the last emitted moveto: */ - gs_fixed_point first; - /* Information about the last emitted operation: */ - int open = 0; /* -1 if last was moveto, 1 if line/curveto, */ - /* 0 if newpath/closepath */ - - - if_debug4('p', "[p]initial (%g,%g), clip [%g..%g)\n", - fixed2float(px), fixed2float(py), - fixed2float(ymin), fixed2float(ymax)); - gx_path_enum_init(&cenum, ppath); - writer.cldev = cldev; - writer.pcls = pcls; - writer.notes = sn_none; + /* + * The point and side of the last moveto (skipped if + * start_side != 0): + */ + gs_fixed_point start; + int start_side; + + /* + * Whether any lines or curves were skipped immediately + * following the moveto: + */ + bool start_skip; + + /* The side of the last point: */ + int side; + + /* The last point with side != 0: */ + gs_fixed_point out; + + /* If the last out-going segment was a lineto, */ + /* its notes: */ + segment_notes out_notes; + + /* + * The following track the emitted segments: + */ + + /* The last point emitted: */ + fixed px = int2fixed(pcls->rect.x); + fixed py = int2fixed(pcls->rect.y); + + /* The point of the last emitted moveto: */ + gs_fixed_point first; + + /* Information about the last emitted operation: */ + int open = 0; /* -1 if last was moveto, 1 if line/curveto, */ + + /* 0 if newpath/closepath */ + + + if_debug4('p', "[p]initial (%g,%g), clip [%g..%g)\n", + fixed2float(px), fixed2float(py), + fixed2float(ymin), fixed2float(ymax)); + gx_path_enum_init(&cenum, ppath); + writer.cldev = cldev; + writer.pcls = pcls; + writer.notes = sn_none; #define set_first_point() (writer.dp = &initial_op) #define first_point() (writer.dp == &initial_op) - set_first_point(); - for ( ; ; ) - { fixed vs[6]; + set_first_point(); + for (;;) { + fixed vs[6]; + #define A vs[0] #define B vs[1] #define C vs[2] #define D vs[3] #define E vs[4] #define F vs[5] - int pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *)vs); - byte *dp; - int code; + int pe_op = gx_path_enum_next(&cenum, (gs_fixed_point *) vs); + byte *dp; + int code; - switch ( pe_op ) - { - case 0: + switch (pe_op) { + case 0: /* If the path is open and needs an implicit close, */ /* do the close and then come here again. */ - if ( open > 0 && implicit_close ) - goto close; + if (open > 0 && implicit_close) + goto close; /* All done. */ pcls->rect.x = fixed2int_var(px); pcls->rect.y = fixed2int_var(py); if_debug2('p', "[p]final (%d,%d)\n", pcls->rect.x, pcls->rect.y); return set_cmd_put_op(dp, cldev, pcls, path_op, 1); - case gs_pe_moveto: + case gs_pe_moveto: /* If the path is open and needs an implicit close, */ /* do a closepath and then redo the moveto. */ - if ( open > 0 && implicit_close ) - { gx_path_enum_backup(&cenum); + if (open > 0 && implicit_close) { + gx_path_enum_backup(&cenum); goto close; - } + } open = -1; start.x = A, start.y = B; start_skip = false; - if ( (start_side = side = which_side(B)) != 0 ) - { out.x = A, out.y = B; - if_debug3('p', "[p]skip moveto (%g,%g) side %d\n", - fixed2float(out.x), fixed2float(out.y), - side); - continue; - } + if ((start_side = side = which_side(B)) != 0) { + out.x = A, out.y = B; + if_debug3('p', "[p]skip moveto (%g,%g) side %d\n", + fixed2float(out.x), fixed2float(out.y), + side); + continue; + } C = A - px, D = B - py; first.x = px = A, first.y = py = B; code = cmd_put_rmoveto(&writer, &C); if_debug2('p', "[p]moveto (%g,%g)\n", fixed2float(px), fixed2float(py)); break; - case gs_pe_lineto: - { int next_side = which_side(B); - segment_notes notes = + case gs_pe_lineto: + { + int next_side = which_side(B); + segment_notes notes = gx_path_enum_notes(&cenum) & keep_notes; - if ( next_side == side && side != 0 ) - { /* Skip a line completely outside the clip region. */ - if ( open < 0 ) - start_skip = true; - out.x = A, out.y = B; - out_notes = notes; - if_debug3('p', "[p]skip lineto (%g,%g) side %d\n", - fixed2float(out.x), fixed2float(out.y), - side); - continue; + if (next_side == side && side != 0) { /* Skip a line completely outside the clip region. */ + if (open < 0) + start_skip = true; + out.x = A, out.y = B; + out_notes = notes; + if_debug3('p', "[p]skip lineto (%g,%g) side %d\n", + fixed2float(out.x), fixed2float(out.y), + side); + continue; } - /* If we skipped any segments, put out a moveto/lineto. */ - if ( side && (px != out.x || py != out.y || first_point()) ) - { C = out.x - px, D = out.y - py; - if ( open < 0 ) - { first = out; - code = cmd_put_rmoveto(&writer, &C); - } - else - code = cmd_put_rlineto(&writer, &C, out_notes); - if ( code < 0 ) - return code; - px = out.x, py = out.y; - if_debug3('p', "[p]catchup %s (%g,%g) for line\n", - (open < 0 ? "moveto" : "lineto"), - fixed2float(px), fixed2float(py)); + /* If we skipped any segments, put out a moveto/lineto. */ + if (side && (px != out.x || py != out.y || first_point())) { + C = out.x - px, D = out.y - py; + if (open < 0) { + first = out; + code = cmd_put_rmoveto(&writer, &C); + } else + code = cmd_put_rlineto(&writer, &C, out_notes); + if (code < 0) + return code; + px = out.x, py = out.y; + if_debug3('p', "[p]catchup %s (%g,%g) for line\n", + (open < 0 ? "moveto" : "lineto"), + fixed2float(px), fixed2float(py)); } - if ( (side = next_side) != 0 ) - { /* Note a vertex going outside the clip region. */ - out.x = A, out.y = B; + if ((side = next_side) != 0) { /* Note a vertex going outside the clip region. */ + out.x = A, out.y = B; } - C = A - px, D = B - py; - px = A, py = B; - open = 1; - code = cmd_put_rlineto(&writer, &C, notes); + C = A - px, D = B - py; + px = A, py = B; + open = 1; + code = cmd_put_rlineto(&writer, &C, notes); } if_debug3('p', "[p]lineto (%g,%g) side %d\n", fixed2float(px), fixed2float(py), side); break; - case gs_pe_closepath: + case gs_pe_closepath: #ifdef DEBUG - { gs_path_enum cpenum; - gs_fixed_point cvs[3]; - int op; - cpenum = cenum; - switch ( op = gx_path_enum_next(&cpenum, cvs) ) - { - case 0: case gs_pe_moveto: - break; - default: - lprintf1("closepath followed by %d, not end/moveto!\n", - op); + { + gs_path_enum cpenum; + gs_fixed_point cvs[3]; + int op; + + cpenum = cenum; + switch (op = gx_path_enum_next(&cpenum, cvs)) { + case 0: + case gs_pe_moveto: + break; + default: + lprintf1("closepath followed by %d, not end/moveto!\n", + op); } } #endif /* A closepath may require drawing an explicit line if */ /* we skipped any segments at the beginning of the path. */ -close: if ( side != start_side ) - { /* If we skipped any segments, put out a moveto/lineto. */ - if ( side && (px != out.x || py != out.y || first_point()) ) - { C = out.x - px, D = out.y - py; + close:if (side != start_side) { /* If we skipped any segments, put out a moveto/lineto. */ + if (side && (px != out.x || py != out.y || first_point())) { + C = out.x - px, D = out.y - py; code = cmd_put_rlineto(&writer, &C, out_notes); - if ( code < 0 ) - return code; + if (code < 0) + return code; px = out.x, py = out.y; if_debug2('p', "[p]catchup line (%g,%g) for close\n", fixed2float(px), fixed2float(py)); - } - if ( open > 0 && start_skip ) - { /* Draw the closing line back to the start. */ + } + if (open > 0 && start_skip) { /* Draw the closing line back to the start. */ C = start.x - px, D = start.y - py; code = cmd_put_rlineto(&writer, &C, sn_none); - if ( code < 0 ) - return code; + if (code < 0) + return code; px = start.x, py = start.y; if_debug2('p', "[p]draw close to (%g,%g)\n", fixed2float(px), fixed2float(py)); - } - } + } + } /* * We don't bother to update side because we know that the * next element after a closepath, if any, must be a moveto. * We must handle explicitly the possibility that the entire * subpath was skipped. */ - if ( implicit_close || open <= 0 ) - { open = 0; + if (implicit_close || open <= 0) { + open = 0; /* * Force writing an explicit moveto if the next subpath * starts with a moveto to the same point where this one @@ -1119,112 +1155,114 @@ close: if ( side != start_side ) */ set_first_point(); continue; - } + } open = 0; px = first.x, py = first.y; code = cmd_put_segment(&writer, cmd_opv_closepath, &A, sn_none); if_debug0('p', "[p]close\n"); break; - case gs_pe_curveto: - { segment_notes notes = + case gs_pe_curveto: + { + segment_notes notes = gx_path_enum_notes(&cenum) & keep_notes; - { fixed bpy, bqy; - int all_side, out_side; - - /* Compute the Y bounds for the clipping check. */ - if ( B < D ) bpy = B, bqy = D; - else bpy = D, bqy = B; - if ( F < bpy ) bpy = F; - else if ( F > bqy ) bqy = F; - all_side = (bqy < ymin ? -1 : bpy > ymax ? 1 : 0); - if ( all_side != 0 ) - { if ( all_side == side ) - { /* Skip a curve entirely outside the clip region. */ - if ( open < 0 ) - start_skip = true; - out.x = E, out.y = F; - out_notes = notes; - if_debug3('p', "[p]skip curveto (%g,%g) side %d\n", - fixed2float(out.x), fixed2float(out.y), - side); - continue; - } - out_side = all_side; - } - else - out_side = which_side(F); - /* If we skipped any segments, put out a moveto/lineto. */ - if ( side && (px != out.x || py != out.y || first_point()) ) - { fixed diff[2]; - diff[0] = out.x - px, diff[1] = out.y - py; - if ( open < 0 ) - { first = out; - code = cmd_put_rmoveto(&writer, diff); + + { + fixed bpy, bqy; + int all_side, out_side; + + /* Compute the Y bounds for the clipping check. */ + if (B < D) + bpy = B, bqy = D; + else + bpy = D, bqy = B; + if (F < bpy) + bpy = F; + else if (F > bqy) + bqy = F; + all_side = (bqy < ymin ? -1 : bpy > ymax ? 1 : 0); + if (all_side != 0) { + if (all_side == side) { /* Skip a curve entirely outside the clip region. */ + if (open < 0) + start_skip = true; + out.x = E, out.y = F; + out_notes = notes; + if_debug3('p', "[p]skip curveto (%g,%g) side %d\n", + fixed2float(out.x), fixed2float(out.y), + side); + continue; + } + out_side = all_side; + } else + out_side = which_side(F); + /* If we skipped any segments, put out a moveto/lineto. */ + if (side && (px != out.x || py != out.y || first_point())) { + fixed diff[2]; + + diff[0] = out.x - px, diff[1] = out.y - py; + if (open < 0) { + first = out; + code = cmd_put_rmoveto(&writer, diff); + } else + code = cmd_put_rlineto(&writer, diff, out_notes); + if (code < 0) + return code; + px = out.x, py = out.y; + if_debug3('p', "[p]catchup %s (%g,%g) for curve\n", + (open < 0 ? "moveto" : "lineto"), + fixed2float(px), fixed2float(py)); } - else - code = cmd_put_rlineto(&writer, diff, out_notes); - if ( code < 0 ) - return code; - px = out.x, py = out.y; - if_debug3('p', "[p]catchup %s (%g,%g) for curve\n", - (open < 0 ? "moveto" : "lineto"), - fixed2float(px), fixed2float(py)); - } - if ( (side = out_side) != 0 ) - { /* Note a vertex going outside the clip region. */ - out.x = E, out.y = F; - } - } - { fixed nx = E, ny = F; - const fixed _ss *optr = vs; - byte op; - - if_debug7('p', "[p]curveto (%g,%g; %g,%g; %g,%g) side %d\n", - fixed2float(A), fixed2float(B), - fixed2float(C), fixed2float(D), - fixed2float(E), fixed2float(F), side); - E -= C, F -= D; - C -= A, D -= B; - A -= px, B -= py; - if ( B == 0 && E == 0 ) - { B = A, E = F, optr++, op = cmd_opv_hvcurveto; - if ( (B ^ D) >= 0 ) - { if ( C == D && E == B ) - op = cmd_opv_hqcurveto; + if ((side = out_side) != 0) { /* Note a vertex going outside the clip region. */ + out.x = E, out.y = F; } - else if ( C == -D && E == -B ) - C = D, op = cmd_opv_hqcurveto; } - else if ( A == 0 && F == 0 ) - { optr++, op = cmd_opv_vhcurveto; - if ( (B ^ C) >= 0 ) - { if ( D == C && E == B ) - op = cmd_opv_vqcurveto; - } - else if ( D == -C && E == -B ) - op = cmd_opv_vqcurveto; + { + fixed nx = E, ny = F; + const fixed _ss *optr = vs; + byte op; + + if_debug7('p', "[p]curveto (%g,%g; %g,%g; %g,%g) side %d\n", + fixed2float(A), fixed2float(B), + fixed2float(C), fixed2float(D), + fixed2float(E), fixed2float(F), side); + E -= C, F -= D; + C -= A, D -= B; + A -= px, B -= py; + if (B == 0 && E == 0) { + B = A, E = F, optr++, op = cmd_opv_hvcurveto; + if ((B ^ D) >= 0) { + if (C == D && E == B) + op = cmd_opv_hqcurveto; + } else if (C == -D && E == -B) + C = D, op = cmd_opv_hqcurveto; + } else if (A == 0 && F == 0) { + optr++, op = cmd_opv_vhcurveto; + if ((B ^ C) >= 0) { + if (D == C && E == B) + op = cmd_opv_vqcurveto; + } else if (D == -C && E == -B) + op = cmd_opv_vqcurveto; + } else if (A == 0 && B == 0) + optr += 2, op = cmd_opv_nrcurveto; + else if (E == 0 && F == 0) + op = cmd_opv_rncurveto; + else + op = cmd_opv_rrcurveto; + px = nx, py = ny; + open = 1; + code = cmd_put_segment(&writer, op, optr, notes); } - else if ( A == 0 && B == 0 ) - optr += 2, op = cmd_opv_nrcurveto; - else if ( E == 0 && F == 0 ) - op = cmd_opv_rncurveto; - else - op = cmd_opv_rrcurveto; - px = nx, py = ny; - open = 1; - code = cmd_put_segment(&writer, op, optr, notes); } - } break; - default: + break; + default: return_error(gs_error_rangecheck); - } - if ( code < 0 ) - return code; + } + if (code < 0) + return code; #undef A #undef B #undef C #undef D #undef E #undef F - } + } } |