summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Stiles <henry.stiles@artifex.com>2012-04-12 09:34:32 -0600
committerHenry Stiles <henry.stiles@artifex.com>2012-04-12 09:34:32 -0600
commit1b355f679fd03a5d5d334b6d74202d9c3d58110b (patch)
tree932c225a5537ef12102f161c21bf1dcb4d2fc1bb
parent3769efbb709889aae39f905dd04b72a81bc37f3d (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.c7
-rw-r--r--gs/base/gxclip2.h5
-rw-r--r--gs/base/gxp1fill.c44
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,