diff options
Diffstat (limited to 'base/gxpcmap.c')
-rw-r--r-- | base/gxpcmap.c | 100 |
1 files changed, 67 insertions, 33 deletions
diff --git a/base/gxpcmap.c b/base/gxpcmap.c index ea81fb00..ebd1de22 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 */ @@ -341,6 +342,23 @@ gx_pattern_accum_alloc(gs_memory_t * mem, gs_memory_t * storage_memory, return fdev; } +gx_pattern_trans_t* +new_pattern_trans_buff(gs_memory_t *mem) +{ + gx_pattern_trans_t *result; + + /* Allocate structure that we will use for the trans pattern */ + result = gs_alloc_struct(mem, gx_pattern_trans_t, &st_pattern_trans, "new_pattern_trans_buff"); + result->transbytes = NULL; + result->pdev14 = NULL; + result->mem = NULL; + result->fill_trans_buffer = NULL; + result->buf = NULL; + result->n_chan = 0; + + return(result); +} + /* * Initialize a pattern accumulator. * Client must already have set instance and bitmap_memory. @@ -392,14 +410,9 @@ pattern_accum_open(gx_device * dev) do this since the transparency code all */ if (pinst->templat.uses_transparency) { /* Allocate structure that we will use for the trans pattern */ - padev->transbuff = gs_alloc_struct(mem,gx_pattern_trans_t,&st_pattern_trans,"pattern_accum_open(trans)"); - padev->transbuff->transbytes = NULL; - padev->transbuff->mem = NULL; - padev->transbuff->pdev14 = NULL; - padev->transbuff->fill_trans_buffer = NULL; - /* n_chan = 0 => padev->transbuff isn't inited. */ - padev->transbuff->n_chan = 0; - padev->transbuff->buf = NULL; + padev->transbuff = new_pattern_trans_buff(mem); + if (padev->transbuff == NULL) + return_error(gs_error_VMerror); } else { padev->transbuff = NULL; } @@ -496,21 +509,6 @@ pattern_accum_open(gx_device * dev) return code; } -gx_pattern_trans_t* -new_pattern_trans_buff(gs_memory_t *mem) -{ - gx_pattern_trans_t *result; - - /* Allocate structure that we will use for the trans pattern */ - result = gs_alloc_struct(mem, gx_pattern_trans_t, &st_pattern_trans, "new_pattern_trans_buff"); - result->transbytes = NULL; - result->pdev14 = NULL; - result->mem = NULL; - result->fill_trans_buffer = NULL; - - return(result); -} - /* Close an accumulator and free the bits. */ static int pattern_accum_close(gx_device * dev) @@ -907,12 +905,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 +991,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 */ } } @@ -1025,7 +1032,7 @@ gx_pattern_cache_update_used(gs_gstate *pgs, ulong used) static void make_bitmap(gx_strip_bitmap *, const gx_device_memory *, gx_bitmap_id, const gs_memory_t *); int gx_pattern_cache_add_entry(gs_gstate * pgs, - gx_device_forward * fdev, gx_color_tile ** pctile) + gx_device_forward * fdev, gx_color_tile ** pctile, gs_gstate* saved) { gx_pattern_cache *pcache; const gs_pattern1_instance_t *pinst; @@ -1070,8 +1077,8 @@ gx_pattern_cache_add_entry(gs_gstate * pgs, * being 0. */ if (mmask != 0 && - fabsf(pinst->step_matrix.tx) <= pinst->size.x && - fabsf(pinst->step_matrix.ty) <= pinst->size.y && + fabsf(pinst->step_matrix.xx) <= pinst->size.x && + fabsf(pinst->step_matrix.yy) <= pinst->size.y && pinst->step_matrix.xy == 0 && pinst->step_matrix.yx == 0) { int y; @@ -1133,10 +1140,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; - if (pinst->templat.uses_transparency) - ctile->blending_mode = ((pdf14_device *)(pgs->device))->blend_mode; + 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); @@ -1181,6 +1192,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) @@ -1230,6 +1261,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; @@ -1366,6 +1398,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); } @@ -1501,6 +1534,7 @@ gx_pattern_load(gx_device_color * pdc, const gs_gstate * pgs, gs_free_object(((gx_device_pattern_accum *)adev)->bitmap_memory, ((gx_device_pattern_accum *)adev)->transbuff, "gx_pattern_load"); + ((gx_device_pattern_accum *)adev)->transbuff = NULL; } dev_proc(adev, close_device)((gx_device *)adev); /* adev was the target of the pdf14 device, so also is no longer retained */ @@ -1537,7 +1571,7 @@ gx_pattern_load(gx_device_color * pdc, const gs_gstate * pgs, } /* We REALLY don't like the following cast.... */ code = gx_pattern_cache_add_entry((gs_gstate *)pgs, - adev, &ctile); + adev, &ctile, saved); if (code >= 0) { if (!gx_pattern_cache_lookup(pdc, pgs, dev, select)) { mlprintf(mem, "Pattern cache lookup failed after insertion!\n"); |