diff options
Diffstat (limited to 'base/gxpcmap.c')
-rw-r--r-- | base/gxpcmap.c | 42 |
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); } |