summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2014-03-07 13:41:01 +0000
committerKen Sharp <ken.sharp@artifex.com>2014-03-07 13:41:01 +0000
commit94c5ecffe4bf66cc91108d99a802c7c2d3b86e0b (patch)
tree3b1b97ee83d52a2b25c8c9c9938b43a5c66828cb
parent4b16c45c3b834efb9ff9608360d3c053e91b1f23 (diff)
downloadghostpdl-94c5ecffe4bf66cc91108d99a802c7c2d3b86e0b.tar.gz
PS interpreter, vector devices and pdfwrite - remove setdash limit of 11
Bug #693916 "setdash does not accept more than 11 elements in the array argument" The PostScript interpreter was already capable of this, it simply required the limit check to be removed. The vector device needed to allocate and free an array of floats, rather than maintain a fixed size array. pdfwrite was teh most complex as it maintains a stack of gstates, and these also needed to be modified to allocate and free the dash array. However the gstate stack wasn't already a garbage collecting structure. Rather than going to the effort of turning it into one I've opted to allocate the dash pattern from non-gc memory. A few PCL files show differences with pdfwrite, because previously pdfwrite would throw an error (more than 11 elements in the dash array) and the stroked lines would degenerate into filled rectangles, whereas now they are drawn as stroked lines with a correct dash pattern. This is much more efficient. The clist remains unmodified, Ray assures me that it will be handled there without problems.
-rw-r--r--gs/Resource/Init/gs_init.ps1
-rw-r--r--gs/base/gdevvec.c14
-rw-r--r--gs/base/gdevvec.h13
-rw-r--r--gs/devices/vector/gdevpdf.c5
-rw-r--r--gs/devices/vector/gdevpdfg.c32
-rw-r--r--gs/devices/vector/gdevpdfx.h3
6 files changed, 50 insertions, 18 deletions
diff --git a/gs/Resource/Init/gs_init.ps b/gs/Resource/Init/gs_init.ps
index 962957df2..fdc96822c 100644
--- a/gs/Resource/Init/gs_init.ps
+++ b/gs/Resource/Init/gs_init.ps
@@ -522,7 +522,6 @@ userdict /.echo.mode //true put
0 .argindex type dup /integertype eq exch /realtype eq or not {
/setdash .systemvar /typecheck signalerror
} if
- 1 .argindex length 11 gt { /setdash .systemvar /limitcheck signalerror } if
//setdash
} odef
/setdevice
diff --git a/gs/base/gdevvec.c b/gs/base/gdevvec.c
index 0b67fb5dc..56cdb518c 100644
--- a/gs/base/gdevvec.c
+++ b/gs/base/gdevvec.c
@@ -457,24 +457,26 @@ gdev_vector_prepare_stroke(gx_device_vector * vdev,
float dash_offset = pis->line_params.dash.offset * scale;
float half_width = pis->line_params.half_width * scale;
- if (pattern_size > max_dash)
- return_error(gs_error_limitcheck);
if (dash_offset != vdev->state.line_params.dash.offset ||
pattern_size != vdev->state.line_params.dash.pattern_size ||
(pattern_size != 0 &&
!dash_pattern_eq(vdev->dash_pattern, &pis->line_params.dash,
scale))
) {
- float pattern[max_dash];
+ float *pattern;
int i, code;
+ pattern = gs_alloc_bytes(vdev->memory->stable_memory, pattern_size * sizeof(float), "vector allocate dash pattern");
for (i = 0; i < pattern_size; ++i)
pattern[i] = pis->line_params.dash.pattern[i] * scale;
code = (*vdev_proc(vdev, setdash))
(vdev, pattern, pattern_size, dash_offset);
if (code < 0)
return code;
- memcpy(vdev->dash_pattern, pattern, pattern_size * sizeof(float));
+ if (vdev->dash_pattern)
+ gs_free_object(vdev->memory->stable_memory, vdev->dash_pattern, "vector free old dash pattern");
+ vdev->dash_pattern = pattern;
+ vdev->dash_pattern_size = pattern_size;
vdev->state.line_params.dash.pattern_size = pattern_size;
vdev->state.line_params.dash.offset = dash_offset;
@@ -816,6 +818,10 @@ gdev_vector_close_file(gx_device_vector * vdev)
FILE *f = vdev->file;
int err;
+ if (vdev->dash_pattern) {
+ gs_free_object(vdev->memory->stable_memory, vdev->dash_pattern, "vector free dash pattern");
+ vdev->dash_pattern = 0;
+ }
if (vdev->bbox_device) {
rc_decrement(vdev->bbox_device->icc_struct, "vector_close(bbox_device->icc_struct");
vdev->bbox_device->icc_struct = NULL;
diff --git a/gs/base/gdevvec.h b/gs/base/gdevvec.h
index 7519d257f..0d1f34393 100644
--- a/gs/base/gdevvec.h
+++ b/gs/base/gdevvec.h
@@ -66,9 +66,6 @@ typedef struct gx_device_vector_s gx_device_vector;
/* Define the maximum size of the output file name. */
#define fname_size (gp_file_name_sizeof - 1)
-/* Define the longest dash pattern we can remember. */
-#define max_dash 11
-
/*
* Define procedures for writing common output elements. Not all devices
* will support all of these elements. Note that these procedures normally
@@ -168,7 +165,8 @@ int gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0,
int open_options; /* see below */\
/* Graphics state */\
gs_imager_state state;\
- float dash_pattern[max_dash];\
+ float *dash_pattern;\
+ uint dash_pattern_size;\
bool fill_used_process_color;\
bool stroke_used_process_color;\
gx_hl_saved_color saved_fill_color;\
@@ -194,7 +192,8 @@ int gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0,
0, /* strmbuf_size */\
0, /* open_options */\
{ 0 }, /* state */\
- { 0 }, /* dash_pattern */\
+ 0, /* dash_pattern */\
+ 0, /* dash pattern size */\
true, /* fill_used_process_color */\
true, /* stroke_used_process_color */\
{ 0 }, /* fill_color ****** WRONG ****** */\
@@ -216,10 +215,10 @@ struct gx_device_vector_s {
/* extern its descriptor for the sake of subclasses. */
extern_st(st_device_vector);
#define public_st_device_vector() /* in gdevvec.c */\
- gs_public_st_suffix_add3_final(st_device_vector, gx_device_vector,\
+ gs_public_st_suffix_add4_final(st_device_vector, gx_device_vector,\
"gx_device_vector", device_vector_enum_ptrs,\
device_vector_reloc_ptrs, gx_device_finalize, st_device, strm, strmbuf,\
- bbox_device)
+ dash_pattern, bbox_device)
#define st_device_vector_max_ptrs (st_device_max_ptrs + 3)
/* ================ Utility procedures ================ */
diff --git a/gs/devices/vector/gdevpdf.c b/gs/devices/vector/gdevpdf.c
index 1caf3ccfc..92dcc7dda 100644
--- a/gs/devices/vector/gdevpdf.c
+++ b/gs/devices/vector/gdevpdf.c
@@ -2998,6 +2998,11 @@ pdf_close(gx_device * dev)
gs_free_object(mem, pdev->Pages, "Free Pages dict");
pdev->Pages = 0;
+ {
+ int i;
+ for (i=0;i < pdev->vgstack_depth;i++)
+ gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "pdfwrite final free stored dash in gstate");
+ }
gs_free_object(pdev->pdf_memory, pdev->vgstack, "pdf_close(graphics state stack)");
cos_release((cos_object_t *)pdev->Namespace_stack, "release Name space stack");
diff --git a/gs/devices/vector/gdevpdfg.c b/gs/devices/vector/gdevpdfg.c
index 7d83f5f17..871e82bce 100644
--- a/gs/devices/vector/gdevpdfg.c
+++ b/gs/devices/vector/gdevpdfg.c
@@ -94,8 +94,19 @@ pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
pdev->vgstack[i].line_params = pdev->state.line_params;
pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
- memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern,
- sizeof(pdev->vgstack[i].dash_pattern));
+ if (pdev->dash_pattern) {
+ if (pdev->vgstack[i].dash_pattern)
+ gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
+ pdev->vgstack[i].dash_pattern = (float *)gs_alloc_bytes(pdev->memory->non_gc_memory, pdev->dash_pattern_size * sizeof(float), "gstate copy dash");
+ memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, pdev->dash_pattern_size * sizeof(float));
+ pdev->vgstack[i].dash_pattern_size = pdev->dash_pattern_size;
+ } else {
+ if (pdev->vgstack[i].dash_pattern) {
+ gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
+ pdev->vgstack[i].dash_pattern = 0;
+ pdev->vgstack[i].dash_pattern_size = 0;
+ }
+ }
pdev->vgstack_depth++;
if (s)
stream_puts(s, "q\n");
@@ -129,8 +140,18 @@ pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
pdev->saved_fill_color = s->saved_fill_color;
pdev->saved_stroke_color = s->saved_stroke_color;
pdev->state.line_params = s->line_params;
- memcpy(pdev->dash_pattern, s->dash_pattern,
- sizeof(s->dash_pattern));
+ if (s->dash_pattern) {
+ if (pdev->dash_pattern)
+ gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
+ pdev->dash_pattern = (float *)gs_alloc_bytes(pdev->memory->stable_memory, s->dash_pattern_size * sizeof(float), "vector allocate dash pattern");
+ pdev->dash_pattern_size = s->dash_pattern_size;
+ } else {
+ if (pdev->dash_pattern) {
+ gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
+ pdev->dash_pattern = 0;
+ pdev->dash_pattern_size = 0;
+ }
+ }
}
/* Restore the viewer's graphic state. */
@@ -201,7 +222,8 @@ pdf_viewer_state_from_imager_state_aux(pdf_viewer_state *pvs, const gs_imager_st
pvs->line_params.dot_length_absolute = pis->line_params.dot_length_absolute;
pvs->line_params.dot_orientation = pis->line_params.dot_orientation;
memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
- memset(pvs->dash_pattern, 0, sizeof(pvs->dash_pattern));
+ pvs->dash_pattern = 0;
+ pvs->dash_pattern_size = 0;
}
/* Copy viewer state from images state. */
diff --git a/gs/devices/vector/gdevpdfx.h b/gs/devices/vector/gdevpdfx.h
index df3a1f156..df73ab137 100644
--- a/gs/devices/vector/gdevpdfx.h
+++ b/gs/devices/vector/gdevpdfx.h
@@ -502,7 +502,8 @@ typedef struct pdf_viewer_state_s {
gx_hl_saved_color saved_fill_color;
gx_hl_saved_color saved_stroke_color;
gx_line_params line_params;
- float dash_pattern[max_dash];
+ float *dash_pattern;
+ uint dash_pattern_size;
gs_id soft_mask_id;
} pdf_viewer_state;