diff options
author | Henry Stiles <henry.stiles@artifex.com> | 2012-04-12 09:34:32 -0600 |
---|---|---|
committer | Henry Stiles <henry.stiles@artifex.com> | 2012-04-12 09:34:32 -0600 |
commit | 1b355f679fd03a5d5d334b6d74202d9c3d58110b (patch) | |
tree | 932c225a5537ef12102f161c21bf1dcb4d2fc1bb | |
parent | 3769efbb709889aae39f905dd04b72a81bc37f3d (diff) |
Fix 692970 - device reference counting incorrect.
The tile clipping device did not properly release its reference to the
target device.
-rw-r--r-- | gs/base/gxclip2.c | 7 | ||||
-rw-r--r-- | gs/base/gxclip2.h | 5 | ||||
-rw-r--r-- | gs/base/gxp1fill.c | 44 |
3 files changed, 47 insertions, 9 deletions
diff --git a/gs/base/gxclip2.c b/gs/base/gxclip2.c index 0b356b498..71ee2092b 100644 --- a/gs/base/gxclip2.c +++ b/gs/base/gxclip2.c @@ -126,6 +126,13 @@ tile_clip_initialize(gx_device_tile_clip * cdev, const gx_strip_bitmap * tiles, return code; } +void +tile_clip_release(gx_device_tile_clip *cdev) +{ + /* release the target reference */ + gx_device_set_target((gx_device_forward *)cdev, NULL); +} + /* Set the phase of the tile. */ void tile_clip_set_phase(gx_device_tile_clip * cdev, int px, int py) diff --git a/gs/base/gxclip2.h b/gs/base/gxclip2.h index b973f1630..b6f9343ee 100644 --- a/gs/base/gxclip2.h +++ b/gs/base/gxclip2.h @@ -41,6 +41,11 @@ int tile_clip_initialize(gx_device_tile_clip * cdev, gs_memory_t *mem); /* + * relase the tile clipping device. + */ +void tile_clip_release(gx_device_tile_clip *cdev); + +/* * Set the phase of the tile -- used in the tiling loop when * the tile doesn't simply fill the plane. */ diff --git a/gs/base/gxp1fill.c b/gs/base/gxp1fill.c index 3d87c56da..86f5c8d63 100644 --- a/gs/base/gxp1fill.c +++ b/gs/base/gxp1fill.c @@ -85,6 +85,11 @@ typedef struct tile_fill_trans_state_s { } tile_fill_trans_state_t; +/* we need some means of detecting if a forwarding clipping device was + installed. If the tile state contains a device different from the + target output device it must be the clipping device. */ +#define CLIPDEV_INSTALLED (state.pcdev != dev) + /* Initialize the filling state. */ static int tile_fill_init(tile_fill_state_t * ptfs, const gx_device_color * pdevc, @@ -373,7 +378,7 @@ gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y, imod(-(int)fastfloor(ptile->step_matrix.ty - state.phase.y + 0.5), bits->rep_height); - if (state.pcdev != dev) + if (CLIPDEV_INSTALLED) tile_clip_set_phase(&state.cdev, px, py); /* RJW: Can we get away with calling the simpler version? Not * if we are working in planar mode because the default @@ -424,6 +429,8 @@ gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y, &tbits, tile_pattern_clist); } } + if (CLIPDEV_INSTALLED) + tile_clip_release((gx_device_tile_clip *) &state.cdev); if(state.cdev.finalize) state.cdev.finalize((gx_device *)&state.cdev); return code; @@ -473,16 +480,20 @@ gx_dc_pure_masked_fill_rect(const gx_device_color * pdevc, if (code < 0) return code; if (state.pcdev == dev || ptile->is_simple) - return (*gx_dc_type_data_pure.fill_rectangle) + code = (*gx_dc_type_data_pure.fill_rectangle) (pdevc, x, y, w, h, state.pcdev, lop, source); else { state.lop = lop; state.source = source; state.fill_rectangle = gx_dc_type_data_pure.fill_rectangle; - return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, + code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, tile_masked_fill); } + if (CLIPDEV_INSTALLED) + tile_clip_release((gx_device_tile_clip *) &state.cdev); + return code; } + int gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc, int x, int y, int w, int h, gx_device * dev, @@ -497,16 +508,20 @@ gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc, if (code < 0) return code; if (state.pcdev == dev || ptile->is_simple) - return (*gx_dc_type_data_ht_binary.fill_rectangle) + code = (*gx_dc_type_data_ht_binary.fill_rectangle) (pdevc, x, y, w, h, state.pcdev, lop, source); else { state.lop = lop; state.source = source; state.fill_rectangle = gx_dc_type_data_ht_binary.fill_rectangle; - return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, + code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, tile_masked_fill); } + if (CLIPDEV_INSTALLED) + tile_clip_release((gx_device_tile_clip *) &state.cdev); + return code; } + int gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc, int x, int y, int w, int h, gx_device * dev, @@ -521,15 +536,18 @@ gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc, if (code < 0) return code; if (state.pcdev == dev || ptile->is_simple) - return (*gx_dc_type_data_ht_colored.fill_rectangle) + code = (*gx_dc_type_data_ht_colored.fill_rectangle) (pdevc, x, y, w, h, state.pcdev, lop, source); else { state.lop = lop; state.source = source; state.fill_rectangle = gx_dc_type_data_ht_colored.fill_rectangle; - return tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, + code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask, tile_masked_fill); } + if (CLIPDEV_INSTALLED) + tile_clip_release((gx_device_tile_clip *) &state.cdev); + return code; } /* @@ -892,8 +910,16 @@ gx_dc_pat_trans_fill_rectangle(const gx_device_color * pdevc, int x, int y, return code; } -/* This fills the transparency buffer rectangles with a pattern - buffer that includes transparency */ +/* This fills the transparency buffer rectangles with a pattern buffer + that includes transparency. NB this procedure does not properly + handle error codes and, consequently, does not attempt to release + the target reference. + + tile_clip_release((gx_device_tile_clip *)&state_clist_trans.cdev) + + needs to be paired with tile_fill_init() to get rid of the device + reference. +*/ int gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax, |