summaryrefslogtreecommitdiff
path: root/base/gxpcmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'base/gxpcmap.c')
-rw-r--r--base/gxpcmap.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/base/gxpcmap.c b/base/gxpcmap.c
index 3be145aef..6f2f5ac29 100644
--- a/base/gxpcmap.c
+++ b/base/gxpcmap.c
@@ -180,7 +180,8 @@ static const gx_device_pattern_accum gs_pattern_accum_device =
gx_default_strip_tile_rect_devn,
NULL, /* alpha_hl_color */
NULL, /* process_page */
- gx_default_transform_pixel_region /* NOT the default forwarding one */
+ gx_default_transform_pixel_region, /* NOT the default forwarding one */
+ gx_default_fill_stroke_path,
},
0, /* target */
0, 0, 0, 0 /* bitmap_memory, bits, mask, instance */
@@ -907,12 +908,14 @@ gstate_set_pattern_cache(gs_gstate * pgs, gx_pattern_cache * pcache)
}
/* Free a Pattern cache entry. */
+/* This will not free a pattern if it is 'locked' which should only be for */
+/* a stroke pattern during fill_stroke_path. */
static void
gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
{
gx_device *temp_device;
- if ((ctile->id != gx_no_bitmap_id) && !ctile->is_dummy) {
+ if ((ctile->id != gx_no_bitmap_id) && !ctile->is_dummy && !ctile->is_locked) {
gs_memory_t *mem = pcache->memory;
/*
@@ -991,18 +994,25 @@ gx_pattern_cache_ensure_space(gs_gstate * pgs, int needed)
{
int code = ensure_pattern_cache(pgs);
gx_pattern_cache *pcache;
+ int start_free_id;
if (code < 0)
return; /* no cache -- just exit */
pcache = pgs->pattern_cache;
-
+ start_free_id = pcache->next; /* for scan wrap check */
/* If too large then start freeing entries */
- /* By starting at 'next', we attempt to first free the oldest entries */
+ /* By starting just after 'next', we attempt to first free the oldest entries */
while (pcache->bits_used + needed > pcache->max_bits &&
pcache->bits_used != 0) {
pcache->next = (pcache->next + 1) % pcache->num_tiles;
gx_pattern_cache_free_entry(pcache, &pcache->tiles[pcache->next]);
+ /* since a pattern may be temporarily locked (stroke pattern for fill_stroke_path) */
+ /* we may not have freed all entries even though we've scanned the entire cache. */
+ /* The following check for wrapping prevents infinite loop if stroke pattern was */
+ /* larger than pcache->max_bits, */
+ if (pcache->next == start_free_id)
+ break; /* we wrapped -- cache may not be empty */
}
}
@@ -1133,12 +1143,14 @@ gx_pattern_cache_add_entry(gs_gstate * pgs,
ctile->is_simple = pinst->is_simple;
ctile->has_overlap = pinst->has_overlap;
ctile->is_dummy = false;
+ ctile->is_locked = false;
if (pinst->templat.uses_transparency) {
/* to work with pdfi get the blend mode out of the saved pgs device */
ctile->blending_mode = ((pdf14_device*)(saved->device))->blend_mode;
}
else
ctile->blending_mode = 0;
+ ctile->trans_group_popped = false;
if (dev_proc(fdev, open_device) != pattern_clist_open_device) {
if (mbits != 0) {
make_bitmap(&ctile->tbits, mbits, gs_next_ids(pgs->memory, 1), pgs->memory);
@@ -1183,6 +1195,26 @@ gx_pattern_cache_add_entry(gs_gstate * pgs,
return 0;
}
+/* set or clear the 'is_locked' flag for a tile in the cache. Used by */
+/* fill_stroke_path to make sure a large stroke pattern stays in the */
+/* cache even if the fill is also a pattern. */
+int
+gx_pattern_cache_entry_set_lock(gs_gstate *pgs, gs_id id, bool new_lock_value)
+{
+ gx_pattern_cache *pcache;
+ gx_color_tile *ctile;
+ int code = ensure_pattern_cache(pgs);
+
+ if (code < 0)
+ return code;
+ pcache = pgs->pattern_cache;
+ ctile = &pcache->tiles[id % pcache->num_tiles];
+ if (ctile->id != id)
+ return_error(gs_error_undefined);
+ ctile->is_locked = new_lock_value;
+ return 0;
+}
+
/* Get entry for reading a pattern from clist. */
int
gx_pattern_cache_get_entry(gs_gstate * pgs, gs_id id, gx_color_tile ** pctile)
@@ -1232,6 +1264,7 @@ gx_pattern_cache_add_dummy_entry(gs_gstate *pgs,
ctile->is_simple = pinst->is_simple;
ctile->has_overlap = pinst->has_overlap;
ctile->is_dummy = true;
+ ctile->is_locked = false;
memset(&ctile->tbits, 0 , sizeof(ctile->tbits));
ctile->tbits.size = pinst->size;
ctile->tbits.id = gs_no_bitmap_id;
@@ -1368,6 +1401,7 @@ gx_pattern_cache_winnow(gx_pattern_cache * pcache,
for (i = 0; i < pcache->num_tiles; ++i) {
gx_color_tile *ctile = &pcache->tiles[i];
+ ctile->is_locked = false; /* force freeing */
if (ctile->id != gx_no_bitmap_id && (*proc) (ctile, proc_data))
gx_pattern_cache_free_entry(pcache, ctile);
}