Blame SOURCES/ghostscript-more-than-11-elements-in-array.patch

629cc8
From d2423464852664218310ae7c5610fb0b6da4218b Mon Sep 17 00:00:00 2001
629cc8
From: Ken Sharp <ken.sharp@artifex.com>
629cc8
Date: Fri, 7 Mar 2014 13:41:01 +0000
629cc8
Subject: [PATCH] PS interpreter, vector devices and pdfwrite - remove setdash
629cc8
 limit of 11
629cc8
629cc8
Bug #693916 "setdash does not accept more than 11 elements in the array argument"
629cc8
629cc8
The PostScript interpreter was already capable of this, it simply required
629cc8
the limit check to be removed. The vector device needed to allocate and
629cc8
free an array of floats, rather than maintain a fixed size array.
629cc8
629cc8
pdfwrite was teh most complex as it maintains a stack of gstates, and these
629cc8
also needed to be modified to allocate and free the dash array. However the
629cc8
gstate stack wasn't already a garbage collecting structure. Rather than going
629cc8
to the effort of turning it into one I've opted to allocate the dash pattern
629cc8
from non-gc memory.
629cc8
629cc8
A few PCL files show differences with pdfwrite, because previously pdfwrite
629cc8
would throw an error (more than 11 elements in the dash array) and the stroked
629cc8
lines would degenerate into filled rectangles, whereas now they are drawn as
629cc8
stroked lines with a correct dash pattern. This is much more efficient.
629cc8
629cc8
The clist remains unmodified, Ray assures me that it will be handled there
629cc8
without problems.
629cc8
---
629cc8
 Resource/Init/gs_init.ps |  1 -
629cc8
 base/gdevpdf.c           |  6 ++++++
629cc8
 base/gdevpdfg.c          | 32 +++++++++++++++++++++++++++-----
629cc8
 base/gdevpdfx.h          |  3 ++-
629cc8
 base/gdevvec.c           | 14 ++++++++++----
629cc8
 base/gdevvec.h           | 13 ++++++-------
629cc8
 6 files changed, 51 insertions(+), 18 deletions(-)
629cc8
629cc8
diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps
629cc8
index 0083fa3..b4a6c48 100644
629cc8
--- a/Resource/Init/gs_init.ps
629cc8
+++ b/Resource/Init/gs_init.ps
629cc8
@@ -518,7 +518,6 @@ userdict /.echo.mode //true put
629cc8
         0 .argindex type dup /integertype eq exch /realtype eq or not {
629cc8
           /setdash .systemvar /typecheck signalerror
629cc8
         } if
629cc8
-        1 .argindex length 11 gt { /setdash .systemvar /limitcheck signalerror } if
629cc8
         //setdash
629cc8
 } odef
629cc8
 /setdevice
629cc8
diff --git a/base/gdevpdf.c b/base/gdevpdf.c
629cc8
index 8416b51..d740cc1 100644
629cc8
--- a/base/gdevpdf.c
629cc8
+++ b/base/gdevpdf.c
629cc8
@@ -2873,6 +2873,12 @@ pdf_close(gx_device * dev)
629cc8
     gs_free_object(mem, pdev->Pages, "Free Pages dict");
629cc8
     pdev->Pages = 0;
629cc8
 
629cc8
+    {
629cc8
+        int i;
629cc8
+        for (i=0;i < pdev->vgstack_depth;i++)
629cc8
+            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "pdfwrite final free stored dash in gstate");
629cc8
+    }
629cc8
+
629cc8
     cos_release((cos_object_t *)pdev->NI_stack, "Release Name Index stack");
629cc8
     gs_free_object(mem, pdev->NI_stack, "Free Name Index stack");
629cc8
     pdev->NI_stack = 0;
629cc8
diff --git a/base/gdevpdfg.c b/base/gdevpdfg.c
629cc8
index 2d4e040..56b24f7 100644
629cc8
--- a/base/gdevpdfg.c
629cc8
+++ b/base/gdevpdfg.c
629cc8
@@ -71,8 +71,19 @@ pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
629cc8
     pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
629cc8
     pdev->vgstack[i].line_params = pdev->state.line_params;
629cc8
     pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
629cc8
-    memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern,
629cc8
-                sizeof(pdev->vgstack[i].dash_pattern));
629cc8
+    if (pdev->dash_pattern) {
629cc8
+        if (pdev->vgstack[i].dash_pattern)
629cc8
+            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
629cc8
+        pdev->vgstack[i].dash_pattern = (float *)gs_alloc_bytes(pdev->memory->non_gc_memory, pdev->dash_pattern_size * sizeof(float), "gstate copy dash");
629cc8
+        memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, pdev->dash_pattern_size * sizeof(float));
629cc8
+        pdev->vgstack[i].dash_pattern_size = pdev->dash_pattern_size;
629cc8
+    } else {
629cc8
+        if (pdev->vgstack[i].dash_pattern) {
629cc8
+            gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "free gstate copy dash");
629cc8
+            pdev->vgstack[i].dash_pattern = 0;
629cc8
+            pdev->vgstack[i].dash_pattern_size = 0;
629cc8
+        }
629cc8
+    }
629cc8
     pdev->vgstack_depth++;
629cc8
     if (s)
629cc8
         stream_puts(s, "q\n");
629cc8
@@ -106,8 +117,18 @@ pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
629cc8
     pdev->saved_fill_color = s->saved_fill_color;
629cc8
     pdev->saved_stroke_color = s->saved_stroke_color;
629cc8
     pdev->state.line_params = s->line_params;
629cc8
-    memcpy(pdev->dash_pattern, s->dash_pattern,
629cc8
-                sizeof(s->dash_pattern));
629cc8
+    if (s->dash_pattern) {
629cc8
+        if (pdev->dash_pattern)
629cc8
+            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
629cc8
+        pdev->dash_pattern = (float *)gs_alloc_bytes(pdev->memory->stable_memory, s->dash_pattern_size * sizeof(float), "vector allocate dash pattern");
629cc8
+        pdev->dash_pattern_size  = s->dash_pattern_size;
629cc8
+    } else {
629cc8
+        if (pdev->dash_pattern) {
629cc8
+            gs_free_object(pdev->memory->stable_memory, pdev->dash_pattern, "vector free dash pattern");
629cc8
+            pdev->dash_pattern = 0;
629cc8
+            pdev->dash_pattern_size = 0;
629cc8
+        }
629cc8
+    }
629cc8
 }
629cc8
 
629cc8
 /* Restore the viewer's graphic state. */
629cc8
@@ -178,7 +199,8 @@ pdf_viewer_state_from_imager_state_aux(pdf_viewer_state *pvs, const gs_imager_st
629cc8
     pvs->line_params.dot_length_absolute = pis->line_params.dot_length_absolute;
629cc8
     pvs->line_params.dot_orientation = pis->line_params.dot_orientation;
629cc8
     memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
629cc8
-    memset(pvs->dash_pattern, 0, sizeof(pvs->dash_pattern));
629cc8
+    pvs->dash_pattern = 0;
629cc8
+    pvs->dash_pattern_size = 0;
629cc8
 }
629cc8
 
629cc8
 /* Copy viewer state from images state. */
629cc8
diff --git a/base/gdevpdfx.h b/base/gdevpdfx.h
629cc8
index bc0545d..69a8257 100644
629cc8
--- a/base/gdevpdfx.h
629cc8
+++ b/base/gdevpdfx.h
629cc8
@@ -500,7 +500,8 @@ typedef struct pdf_viewer_state_s {
629cc8
     gx_hl_saved_color saved_fill_color;
629cc8
     gx_hl_saved_color saved_stroke_color;
629cc8
     gx_line_params line_params;
629cc8
-    float dash_pattern[max_dash];
629cc8
+    float *dash_pattern;
629cc8
+    uint dash_pattern_size;
629cc8
     gs_id soft_mask_id;
629cc8
 } pdf_viewer_state;
629cc8
 
629cc8
diff --git a/base/gdevvec.c b/base/gdevvec.c
629cc8
index ddf787e..ac006f5 100644
629cc8
--- a/base/gdevvec.c
629cc8
+++ b/base/gdevvec.c
629cc8
@@ -457,24 +457,26 @@ gdev_vector_prepare_stroke(gx_device_vector * vdev,
629cc8
         float dash_offset = pis->line_params.dash.offset * scale;
629cc8
         float half_width = pis->line_params.half_width * scale;
629cc8
 
629cc8
-        if (pattern_size > max_dash)
629cc8
-            return_error(gs_error_limitcheck);
629cc8
         if (dash_offset != vdev->state.line_params.dash.offset ||
629cc8
             pattern_size != vdev->state.line_params.dash.pattern_size ||
629cc8
             (pattern_size != 0 &&
629cc8
              !dash_pattern_eq(vdev->dash_pattern, &pis->line_params.dash,
629cc8
                               scale))
629cc8
             ) {
629cc8
-            float pattern[max_dash];
629cc8
+            float *pattern;
629cc8
             int i, code;
629cc8
 
629cc8
+            pattern = gs_alloc_bytes(vdev->memory->stable_memory, pattern_size * sizeof(float), "vector allocate dash pattern");
629cc8
             for (i = 0; i < pattern_size; ++i)
629cc8
                 pattern[i] = pis->line_params.dash.pattern[i] * scale;
629cc8
             code = (*vdev_proc(vdev, setdash))
629cc8
                 (vdev, pattern, pattern_size, dash_offset);
629cc8
             if (code < 0)
629cc8
                 return code;
629cc8
-            memcpy(vdev->dash_pattern, pattern, pattern_size * sizeof(float));
629cc8
+            if (vdev->dash_pattern)
629cc8
+                gs_free_object(vdev->memory->stable_memory, vdev->dash_pattern, "vector free old dash pattern");
629cc8
+            vdev->dash_pattern = pattern;
629cc8
+            vdev->dash_pattern_size = pattern_size;
629cc8
 
629cc8
             vdev->state.line_params.dash.pattern_size = pattern_size;
629cc8
             vdev->state.line_params.dash.offset = dash_offset;
629cc8
@@ -816,6 +818,10 @@ gdev_vector_close_file(gx_device_vector * vdev)
629cc8
     FILE *f = vdev->file;
629cc8
     int err;
629cc8
 
629cc8
+    if (vdev->dash_pattern) {
629cc8
+        gs_free_object(vdev->memory->stable_memory, vdev->dash_pattern, "vector free dash pattern");
629cc8
+        vdev->dash_pattern = 0;
629cc8
+    }
629cc8
     if (vdev->bbox_device) {
629cc8
         rc_decrement(vdev->bbox_device->icc_struct, "vector_close(bbox_device->icc_struct");
629cc8
         vdev->bbox_device->icc_struct = NULL;
629cc8
diff --git a/base/gdevvec.h b/base/gdevvec.h
629cc8
index 1a3eece..385e126 100644
629cc8
--- a/base/gdevvec.h
629cc8
+++ b/base/gdevvec.h
629cc8
@@ -66,9 +66,6 @@ typedef struct gx_device_vector_s gx_device_vector;
629cc8
 /* Define the maximum size of the output file name. */
629cc8
 #define fname_size (gp_file_name_sizeof - 1)
629cc8
 
629cc8
-/* Define the longest dash pattern we can remember. */
629cc8
-#define max_dash 11
629cc8
-
629cc8
 /*
629cc8
  * Define procedures for writing common output elements.  Not all devices
629cc8
  * will support all of these elements.  Note that these procedures normally
629cc8
@@ -168,7 +165,8 @@ int gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0,
629cc8
         int open_options;	/* see below */\
629cc8
                 /* Graphics state */\
629cc8
         gs_imager_state state;\
629cc8
-        float dash_pattern[max_dash];\
629cc8
+        float *dash_pattern;\
629cc8
+        uint dash_pattern_size;\
629cc8
         bool fill_used_process_color;\
629cc8
         bool stroke_used_process_color;\
629cc8
         gx_hl_saved_color saved_fill_color;\
629cc8
@@ -194,7 +192,8 @@ int gdev_vector_dorect(gx_device_vector * vdev, fixed x0, fixed y0,
629cc8
         0,		/* strmbuf_size */\
629cc8
         0,		/* open_options */\
629cc8
          { 0 },		/* state */\
629cc8
-         { 0 },		/* dash_pattern */\
629cc8
+        0,      /* dash_pattern */\
629cc8
+        0,      /* dash pattern size */\
629cc8
         true,		/* fill_used_process_color */\
629cc8
         true,		/* stroke_used_process_color */\
629cc8
          { 0 },		/* fill_color ****** WRONG ****** */\
629cc8
@@ -216,10 +215,10 @@ struct gx_device_vector_s {
629cc8
 /* extern its descriptor for the sake of subclasses. */
629cc8
 extern_st(st_device_vector);
629cc8
 #define public_st_device_vector()	/* in gdevvec.c */\
629cc8
-  gs_public_st_suffix_add3_final(st_device_vector, gx_device_vector,\
629cc8
+  gs_public_st_suffix_add4_final(st_device_vector, gx_device_vector,\
629cc8
     "gx_device_vector", device_vector_enum_ptrs,\
629cc8
     device_vector_reloc_ptrs, gx_device_finalize, st_device, strm, strmbuf,\
629cc8
-    bbox_device)
629cc8
+    dash_pattern, bbox_device)
629cc8
 #define st_device_vector_max_ptrs (st_device_max_ptrs + 3)
629cc8
 
629cc8
 /* ================ Utility procedures ================ */
629cc8
-- 
629cc8
2.14.3
629cc8