summaryrefslogtreecommitdiff
path: root/gs
diff options
context:
space:
mode:
authorHenry Stiles <henry.stiles@artifex.com>1998-09-04 15:53:41 +0000
committerHenry Stiles <henry.stiles@artifex.com>1998-09-04 15:53:41 +0000
commit6382283b6f812883c171bb654cc1b10c58d53051 (patch)
tree10256af38a35d3ddeb37cd598b850bb5647ac350 /gs
parent35bf5548df5eed229be44891c4e8b940f37d8d8a (diff)
gs5.38
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@396 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs')
-rw-r--r--gs/current.txt4
-rw-r--r--gs/lib/gs_init.ps2
-rw-r--r--gs/news59
-rw-r--r--gs/src/gdevpdfi.c15
-rw-r--r--gs/src/gdevpsdp.c40
-rw-r--r--gs/src/gsalloc.c150
-rw-r--r--gs/src/gsalloc.h13
-rw-r--r--gs/src/gscolor2.c5
-rw-r--r--gs/src/gscsepr.c5
-rw-r--r--gs/src/gscspace.c32
-rw-r--r--gs/src/gsmalloc.c1
-rw-r--r--gs/src/gsmemlok.c9
-rw-r--r--gs/src/gsmemory.c6
-rw-r--r--gs/src/gsmemory.h5
-rw-r--r--gs/src/gsmemraw.h17
-rw-r--r--gs/src/gsnogc.c94
-rw-r--r--gs/src/gsparam.c17
-rw-r--r--gs/src/gspcolor.c5
-rw-r--r--gs/src/gsstate.c34
-rw-r--r--gs/src/gxalloc.h28
-rw-r--r--gs/src/gxclip2.c3
-rw-r--r--gs/src/gxcspace.h20
-rw-r--r--gs/src/gxp1fill.c22
-rw-r--r--gs/src/iparam.c6
-rw-r--r--gs/src/version.mak6
-rw-r--r--gs/src/zfileio.c6
26 files changed, 415 insertions, 189 deletions
diff --git a/gs/current.txt b/gs/current.txt
index 3e8a9c461..62435efa2 100644
--- a/gs/current.txt
+++ b/gs/current.txt
@@ -30,8 +30,8 @@ New features (since release 5.10)
(This is not a complete list of new features: see NEWS for details.)
A number of PostScript LanguageLevel 3 features are implemented: ImageType 4
-images, CIEBasedDEF[G] color spaces, idiom recognition, shfill (partial
-support), CloseSource/CloseTarget.
+images, Type 32 fonts / CIDFontType 4 fonts, CIEBasedDEF[G] color spaces,
+idiom recognition, shfill (partial support), CloseSource/CloseTarget.
More of Display PostScript is implemented: view clipping, DevicePixel color
space, context creation with private local VM, ImageType 2 images,
diff --git a/gs/lib/gs_init.ps b/gs/lib/gs_init.ps
index c5ee5662f..b92b668a6 100644
--- a/gs/lib/gs_init.ps
+++ b/gs/lib/gs_init.ps
@@ -31,7 +31,7 @@
% Check the interpreter revision. NOTE: the interpreter code requires
% that the first non-comment token in this file be an integer.
-537
+538
dup revision ne
{ (gs: Interpreter revision \() print revision 10 string cvs print
(\) does not match gs_init.ps revision \() print 10 string cvs print
diff --git a/gs/news b/gs/news
index 83d30bafc..26dac1120 100644
--- a/gs/news
+++ b/gs/news
@@ -29,6 +29,65 @@ Procedures, Utilities, Drivers, Platforms, Fonts, Interpreter, Streams
(included under Interpreter through release 2.9.9), Library. Changes marked
with a * were made available as patches to a previous release.
+Version 5.38(beta) (9/3/98)
+===========================
+
+The sole purpose of this release was to fix some obscure bugs detected by
+the Genoa tests and by another Aladdin project.
+
+Documentation
+-------------
+
+Updates the list of implemented PostScript LanguageLevel 3 features.
+(current.txt)
+
+Drivers
+-------
+
+Fixes problems:
+ - The PDF writer did the wrong thing for multi-source images with
+more than 180 bytes of data (total) per scan line. (gdevpdfi.c)
+ - If one used setdistillerparams, [g]restore caused a rangecheck in
+.setpagedevice. ****** DISABLED FOR DCT DICTS, SINCE THIS CAUSES A SEGV
+****** (gdevpsdp.c)
+
+Interpreter
+-----------
+
+Fixes problems:
+ - 0-length parameter arrays were given an arbitrary type, confusing
+clients. (iparam.c)
+ - EOD on a write stream caused an error. (zfileio.c)
+
+Library
+-------
+
+Fixes problems:
+ - 0-length parameter arrays confused clients that wanted arrays of a
+particular type. (gsparam.c)
+ - Patterns with XStep or YStep smaller than the bounding box didn't
+work properly. (gxp1fill.c)
+ - Resizing an object sometimes copied it unnecessarily. (gsalloc.c)
+ - Freeing the shared part of a graphics state didn't free its
+sub-objects. (gsstate.c)
+ - The standard allocator didn't free its initial (self-containing)
+chunk when asked to free itself. (gsalloc.c)
+ - The standard allocator didn't attempt to merge free blocks before
+giving up. We implemented this by adding another virtual procedure to
+allocators, consolidate_free. (gsmemory.h, gsmemraw.h, gsalloc.c,
+gsmalloc.c, gsmemlok.c, gsmemory.c)
+ - The free object merging algorithm thought there were free objects
+even when there weren't. (Small performance bug only.) (gsalloc.c)
+
+Adds some more tracing to pattern filling. (gxclip2.c, gxp1fill.c)
+
+Replaces the cs_alloc, cs_copy, and cs_undo_alloc macros with procedures.
+(gxcspace.h, gscolor2.c, gscsepr.c, gscspace.c, gspcolor.c)
+
+Moves the free-object merging code from gsnogc.c to gsalloc.c, so it can be
+used even in systems that have a garbage collector. (gsalloc.h, gxalloc.h,
+gsalloc.c, gsnogc.c)
+
Version 5.37(beta) (8/31/98)
============================
diff --git a/gs/src/gdevpdfi.c b/gs/src/gdevpdfi.c
index cb8d377e5..56dc307cc 100644
--- a/gs/src/gdevpdfi.c
+++ b/gs/src/gdevpdfi.c
@@ -979,7 +979,6 @@ gdev_pdf_begin_image(gx_device * dev,
if (pim->ImageMask)
pdf_set_color(pdev, gx_dc_pure_color(pdcolor), &pdev->fill_color,
"rg");
-/****** DOESN'T DO COMPRESSION YET ******/
{
gs_matrix mat;
gs_matrix bmat;
@@ -1041,19 +1040,21 @@ pdf_image_plane_data(gx_device * dev, gx_image_enum_common_t * info,
for (y = 0; y < h; ++y) {
if (nplanes > 1) {
/* Flip the data in blocks before writing. */
+ int pi;
uint count = bcount;
+ uint offset = 0;
+ const byte *bit_planes[gs_image_max_components];
+ for (pi = 0; pi < nplanes; ++pi)
+ bit_planes[pi] = planes[pi].data + planes[pi].raster * y;
while (count) {
uint flip_count = min(count, row_bytes / nplanes);
- const byte *bit_planes[gs_image_max_components];
- int pi;
- for (pi = 0; pi < nplanes; ++pi)
- bit_planes[pi] = planes[pi].data + planes[pi].raster * y;
- image_flip_planes(row, bit_planes, 0, flip_count, nplanes,
- pie->plane_depths[0]);
+ image_flip_planes(row, bit_planes, offset, flip_count,
+ nplanes, pie->plane_depths[0]);
sputs(pie->writer.binary.strm, row, flip_count * nplanes,
&ignore);
+ offset += flip_count;
count -= flip_count;
}
} else {
diff --git a/gs/src/gdevpsdp.c b/gs/src/gdevpsdp.c
index f35f7c589..74c882754 100644
--- a/gs/src/gdevpsdp.c
+++ b/gs/src/gdevpsdp.c
@@ -124,17 +124,32 @@ typedef stream_state_proc_get_params((*ss_get_params_t), stream_state);
private int
psdf_CF_get_params(gs_param_list * plist, const stream_state * ss, bool all)
{
- return s_CF_get_params(plist, (const stream_CF_state *)ss, all);
+ return (ss == 0 ? 0 :
+ s_CF_get_params(plist, (const stream_CF_state *)ss, all));
}
private int
psdf_DCT_get_params(gs_param_list * plist, const stream_state * ss, bool all)
{
- return s_DCTE_get_params(plist, (const stream_DCT_state *)ss, all);
+ int code = (ss == 0 ? 0 :
+ s_DCTE_get_params(plist, (const stream_DCT_state *)ss, all));
+ /*
+ * Add dummy Columns, Rows, and Colors parameters so that put_params
+ * won't complain.
+ */
+ int dummy_size = 8, dummy_colors = 3;
+
+ if (code < 0 ||
+ (code = param_write_int(plist, "Columns", &dummy_size)) < 0 ||
+ (code = param_write_int(plist, "Rows", &dummy_size)) < 0 ||
+ (code = param_write_int(plist, "Colors", &dummy_colors)) < 0
+ )
+ return code;
+ return 0;
}
/*
- * Get an image Dict parameter. Note that we return an empty dictionary if
- * the parameter has never been set.
+ * Get an image Dict parameter. Note that we return a default (usually
+ * empty) dictionary if the parameter has never been set.
*/
private int
psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname,
@@ -148,8 +163,7 @@ psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname,
dict.size = 12; /* enough for all param dicts we know about */
if ((code = param_begin_write_dict(plist, pname, &dict, false)) < 0)
return code;
- if (ss != 0)
- code = (*get_params) (dict.list, ss, false);
+ code = (*get_params)(dict.list, ss, false);
param_end_write_dict(plist, pname, &dict);
return code;
}
@@ -410,13 +424,20 @@ psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname,
ss = 0;
break;
case 0:{
+ /******
+ ****** THIS CAUSES A SEGV FOR DCT FILTERS, BECAUSE
+ ****** THEY DON'T INTIALIZE PROPERLY.
+ ******/
+ if (template != &s_DCTE_template) {
stream_state *ss_new =
- s_alloc_state(mem, template->stype, pname);
+ s_alloc_state(mem, template->stype, pname);
if (ss_new == 0)
return_error(gs_error_VMerror);
ss_new->template = template;
- code = (*put_params) (dict.list, ss_new);
+ if (template->set_defaults)
+ (*template->set_defaults)(ss_new);
+ code = (*put_params)(dict.list, ss_new);
if (code < 0) {
param_signal_error(plist, pname, code);
/* Make sure we free the new state. */
@@ -424,11 +445,12 @@ psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname,
} else
ss = ss_new;
}
+ }
param_end_read_dict(plist, pname, &dict);
}
if (*pss != ss) {
if (ss) {
-/****** FREE SUBSIDIARY OBJECTS -- HOW? ******/
+ /****** FREE SUBSIDIARY OBJECTS -- HOW? ******/
gs_free_object(mem, *pss, pname);
}
*pss = ss;
diff --git a/gs/src/gsalloc.c b/gs/src/gsalloc.c
index c28803bfb..6658bb2d8 100644
--- a/gs/src/gsalloc.c
+++ b/gs/src/gsalloc.c
@@ -104,6 +104,7 @@ private gs_memory_proc_resize_object(i_resize_object);
private gs_memory_proc_free_object(i_free_object);
private gs_memory_proc_status(i_status);
private gs_memory_proc_free_all(i_free_all);
+private gs_memory_proc_consolidate_free(i_consolidate_free);
/* Object memory procedures */
private gs_memory_proc_alloc_bytes(i_alloc_bytes);
@@ -132,6 +133,7 @@ const gs_memory_procs_t gs_ref_memory_procs =
i_free_object,
i_status,
i_free_all,
+ i_consolidate_free,
/* Object memory procedures */
i_alloc_bytes,
i_alloc_struct,
@@ -169,6 +171,7 @@ ialloc_alloc_state(gs_raw_memory_t * parent, uint chunk_size)
iimem->parent = parent;
iimem->chunk_size = chunk_size;
iimem->large_size = ((chunk_size / 4) & -obj_align_mod) + 1;
+ iimem->is_controlled = false;
iimem->gc_status.vm_threshold = chunk_size * 3L;
iimem->gc_status.max_vm = max_long;
iimem->gc_status.psignal = NULL;
@@ -230,6 +233,7 @@ ialloc_add_chunk(gs_ref_memory_t *imem, ulong space, client_name_t cname)
chunk_t *cp;
/* Allow acquisition of this chunk. */
+ imem->is_controlled = false;
imem->large_size = imem->chunk_size;
imem->limit = max_long;
imem->gc_status.max_vm = max_long;
@@ -250,6 +254,7 @@ ialloc_add_chunk(gs_ref_memory_t *imem, ulong space, client_name_t cname)
imem->procs.alloc_string_immovable = imem->procs.alloc_string;
/* Disable acquisition of additional chunks. */
+ imem->is_controlled = true;
imem->limit = 0;
return (cp ? 0 : gs_note_error(gs_error_VMerror));
@@ -305,12 +310,12 @@ ialloc_reset_free(gs_ref_memory_t * mem)
/* vm_threshold, max_vm, or enabled, or after a GC. */
void
ialloc_set_limit(register gs_ref_memory_t * mem)
-{ /*
- * The following code is intended to set the limit so that
- * we stop allocating when allocated + previous_status.allocated
- * exceeds the lesser of max_vm or (if GC is enabled)
- * gc_allocated + vm_threshold.
- */
+{ /*
+ * The following code is intended to set the limit so that
+ * we stop allocating when allocated + previous_status.allocated
+ * exceeds the lesser of max_vm or (if GC is enabled)
+ * gc_allocated + vm_threshold.
+ */
ulong max_allocated =
(mem->gc_status.max_vm > mem->previous_status.allocated ?
mem->gc_status.max_vm - mem->previous_status.allocated :
@@ -359,16 +364,14 @@ i_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname)
alloc_free_chunk(cp, imem);
}
}
- if (free_mask & FREE_ALL_STRUCTURES) {
- /* Note that the allocator is unusable after doing this. */
+ if (free_mask & FREE_ALL_ALLOCATOR) {
+ /* Free the chunk holding the allocator itself. */
for (cp = imem->clast; cp != 0; cp = cp->cprev)
if (cp->cbase + sizeof(obj_header_t) == (byte *)mem) {
- gs_free_object(imem->parent, cp, cname);
+ alloc_free_chunk(cp, imem);
break;
}
}
- if (free_mask & FREE_ALL_ALLOCATOR)
- gs_free_object(imem->parent, imem, cname);
}
/* ================ Accessors ================ */
@@ -577,12 +580,14 @@ i_resize_object(gs_memory_t * mem, void *obj, uint new_num_elements,
gs_memory_type_ptr_t pstype = pp->o_type;
ulong old_size = pre_obj_contents_size(pp);
ulong new_size = (ulong) pstype->ssize * new_num_elements;
+ ulong new_size_rounded;
void *new_obj;
- if ((byte *) obj + obj_align_round(old_size) == imem->cc.cbot &&
- imem->cc.ctop - imem->cc.cbot > new_size + obj_align_mod
+ if ((byte *)obj + obj_align_round(old_size) == imem->cc.cbot &&
+ imem->cc.ctop - (byte *)obj >=
+ (new_size_rounded = obj_align_round(new_size))
) {
- imem->cc.cbot = (byte *) obj + obj_align_round(new_size);
+ imem->cc.cbot = (byte *)obj + new_size_rounded;
pp->o_size = new_size;
if_debug8('A', "[a%d:%c%c ]%s %s(%lu=>%lu) 0x%lx\n",
imem->space,
@@ -691,7 +696,8 @@ i_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
cl.memory = imem;
cl.cp = 0;
if (chunk_locate_ptr(ptr, &cl)) {
- alloc_free_chunk(cl.cp, imem);
+ if (!imem->is_controlled)
+ alloc_free_chunk(cl.cp, imem);
return;
}
/* Don't overwrite even if gs_alloc_debug is set. */
@@ -899,10 +905,13 @@ alloc_obj(gs_ref_memory_t * mem, ulong lsize, gs_memory_type_ptr_t pstype,
obj_header_t *ptr;
if (lsize >= mem->large_size || immovable) {
+ /*
+ * Give the object a chunk all its own. Note that this case does
+ * not occur if is_controlled is true.
+ */
ulong asize =
((lsize + obj_align_mask) & -obj_align_mod) +
sizeof(obj_header_t);
- /* Give it a chunk all its own. */
chunk_t *cp =
alloc_acquire_chunk(mem, asize + sizeof(chunk_head_t), false,
"large object chunk");
@@ -915,16 +924,24 @@ alloc_obj(gs_ref_memory_t * mem, ulong lsize, gs_memory_type_ptr_t pstype,
pre_obj_set_large_size(ptr, lsize);
} else {
uint asize = obj_size_round((uint) lsize);
+ bool consolidate = mem->is_controlled;
while (mem->cc.ctop -
(byte *) (ptr = (obj_header_t *) mem->cc.cbot)
<= asize + sizeof(obj_header_t)) {
- /* Add another chunk. */
- chunk_t *cp =
- alloc_add_chunk(mem, (ulong)mem->chunk_size, "chunk");
-
- if (cp == 0)
- return 0;
+ if (consolidate) {
+ /* Try consolidating free space. */
+ gs_consolidate_free((gs_memory_t *)mem);
+ consolidate = false;
+ continue;
+ } else {
+ /* Add another chunk. */
+ chunk_t *cp =
+ alloc_add_chunk(mem, (ulong)mem->chunk_size, "chunk");
+
+ if (cp == 0)
+ return 0;
+ }
}
mem->cc.cbot = (byte *) ptr + asize;
ptr->o_large = 0;
@@ -936,6 +953,86 @@ alloc_obj(gs_ref_memory_t * mem, ulong lsize, gs_memory_type_ptr_t pstype,
return ptr;
}
+/* Consolidate free objects. */
+void
+ialloc_consolidate_free(gs_ref_memory_t *mem)
+{
+ chunk_t *cp;
+ chunk_t *cprev;
+ /*
+ * We're going to recompute lost.objects, by subtracting the
+ * amount of space reclaimed minus the amount of that space that
+ * was on free lists.
+ */
+ ulong found = 0;
+
+ alloc_close_chunk(mem);
+
+ /* Visit chunks in reverse order to encourage LIFO behavior. */
+ for (cp = mem->clast; cp != 0; cp = cprev) {
+ obj_header_t *begin_free = 0;
+
+ cprev = cp->cprev;
+ SCAN_CHUNK_OBJECTS(cp)
+ DO_ALL
+ if (pre->o_type == &st_free) {
+ if (begin_free == 0)
+ begin_free = pre;
+ } else
+ begin_free = 0;
+ END_OBJECTS_SCAN
+ if (begin_free) {
+ /* We found free objects at the top of the object area. */
+ int i;
+
+ found += (byte *)cp->cbot - (byte *)begin_free;
+ /* Remove the free objects from the freelists. */
+ for (i = 0; i < num_freelists; i++) {
+ obj_header_t *pfree;
+ obj_header_t **ppfprev = &mem->freelists[i];
+ uint free_size =
+ (i << log2_obj_align_mod) + sizeof(obj_header_t);
+
+ while ((pfree = *ppfprev) != 0)
+ if (ptr_ge(pfree, begin_free) &&
+ ptr_lt(pfree, cp->cbot)
+ ) { /* We're removing an object. */
+ *ppfprev = *(obj_header_t **) pfree;
+ found -= free_size;
+ } else
+ ppfprev = (obj_header_t **) pfree;
+ }
+ } else
+ begin_free = (obj_header_t *)cp->cbot;
+ if (begin_free == (obj_header_t *) cp->cbase &&
+ cp->ctop == cp->climit
+ ) { /* The entire chunk is free. */
+ chunk_t *cnext = cp->cnext;
+
+ if (!mem->is_controlled)
+ alloc_free_chunk(cp, mem);
+ if (mem->pcc == cp)
+ mem->pcc =
+ (cnext == 0 ? cprev : cprev == 0 ? cnext :
+ cprev->cbot - cprev->ctop >
+ cnext->cbot - cnext->ctop ? cprev :
+ cnext);
+ } else if (begin_free != (obj_header_t *)cp->cbot) {
+ if_debug4('a', "[a]resetting chunk 0x%lx cbot from 0x%lx to 0x%lx (%lu free)\n",
+ (ulong) cp, (ulong) cp->cbot, (ulong) begin_free,
+ (ulong) ((byte *) cp->cbot - (byte *) begin_free));
+ cp->cbot = (byte *) begin_free;
+ }
+ }
+ mem->lost.objects -= found;
+ alloc_open_chunk(mem);
+}
+private void
+i_consolidate_free(gs_memory_t *mem)
+{
+ ialloc_consolidate_free((gs_ref_memory_t *)mem);
+}
+
/* ================ Roots ================ */
/* Register a root. */
@@ -1192,13 +1289,19 @@ alloc_unlink_chunk(chunk_t * cp, gs_ref_memory_t * mem)
}
}
-/* Free a chunk. This is exported for the GC. */
+/*
+ * Free a chunk. This is exported for the GC. Since we eventually use
+ * this to free the chunk containing the allocator itself, we must be
+ * careful not to reference anything in the allocator after freeing the
+ * chunk data.
+ */
void
alloc_free_chunk(chunk_t * cp, gs_ref_memory_t * mem)
{
gs_raw_memory_t *parent = mem->parent;
alloc_unlink_chunk(cp, mem);
+ mem->allocated -= st_chunk.ssize;
if (mem->cfreed.cp == cp)
mem->cfreed.cp = 0;
if (cp->outer == 0) {
@@ -1208,7 +1311,6 @@ alloc_free_chunk(chunk_t * cp, gs_ref_memory_t * mem)
gs_free_object(parent, cdata, "alloc_free_chunk(data)");
} else
cp->outer->inner_count--;
- mem->allocated -= st_chunk.ssize;
gs_free_object(parent, cp, "alloc_free_chunk(chunk struct)");
}
diff --git a/gs/src/gsalloc.h b/gs/src/gsalloc.h
index 3670e427c..910821ffb 100644
--- a/gs/src/gsalloc.h
+++ b/gs/src/gsalloc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1995, 1998 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -33,14 +33,14 @@ typedef struct gs_ref_memory_s gs_ref_memory_t;
* Define a structure and interface for GC-related allocator state.
*/
typedef struct gs_memory_gc_status_s {
- /* Set by client */
+ /* Set by client */
long vm_threshold; /* GC interval */
long max_vm; /* maximum allowed allocation */
int *psignal; /* if not NULL, store signal_value */
- /* here if we go over the vm_threshold */
+ /* here if we go over the vm_threshold */
int signal_value; /* value to store in *psignal */
bool enabled; /* auto GC enabled if true */
- /* Set by allocator */
+ /* Set by allocator */
long requested; /* amount of last failing request */
} gs_memory_gc_status_t;
void gs_memory_gc_status(P2(const gs_ref_memory_t *, gs_memory_gc_status_t *));
@@ -57,7 +57,7 @@ gs_ref_memory_t *ialloc_alloc_state(P2(gs_raw_memory_t *, uint));
/*
* Add a chunk to an externally controlled allocator. Such allocators
* allocate all objects as immovable, are not garbage-collected, and
- * don't attempt to acquire additional memory on their own.
+ * don't attempt to acquire additional memory (or free chunks) on their own.
*/
int ialloc_add_chunk(P3(gs_ref_memory_t *, ulong, client_name_t));
@@ -75,4 +75,7 @@ void ialloc_reset_free(P1(gs_ref_memory_t *));
/* Set the cached allocation limit of an alloctor from its GC parameters. */
void ialloc_set_limit(P1(gs_ref_memory_t *));
+/* Consolidate free objects. */
+void ialloc_consolidate_free(P1(gs_ref_memory_t *));
+
#endif /* gsalloc_INCLUDED */
diff --git a/gs/src/gscolor2.c b/gs/src/gscolor2.c
index b56c6447c..c737efa3c 100644
--- a/gs/src/gscolor2.c
+++ b/gs/src/gscolor2.c
@@ -308,11 +308,14 @@ gs_cspace_build_Indexed(
{
gs_color_space *pcspace = 0;
gs_indexed_params *pindexed = 0;
+ int code;
if ((pbase_cspace == 0) || !pbase_cspace->type->can_be_base_space)
return_error(gs_error_rangecheck);
- cs_alloc(pcspace, &gs_color_space_type_Indexed, pmem);
+ code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Indexed, pmem);
+ if (code < 0)
+ return code;
pindexed = &(pcspace->params.indexed);
if (ptbl == 0) {
pindexed->lookup.map =
diff --git a/gs/src/gscsepr.c b/gs/src/gscsepr.c
index f75220012..44cdeeed9 100644
--- a/gs/src/gscsepr.c
+++ b/gs/src/gscsepr.c
@@ -207,11 +207,14 @@ gs_cspace_build_Separation(
{
gs_color_space *pcspace = 0;
gs_separation_params *pcssepr = 0;
+ int code;
if (palt_cspace == 0 || !palt_cspace->type->can_be_alt_space)
return_error(gs_error_rangecheck);
- cs_alloc(pcspace, &gs_color_space_type_Separation, pmem);
+ code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Separation, pmem);
+ if (code < 0)
+ return code;
pcssepr = &pcspace->params.separation;
pcssepr->map = alloc_separation_map(palt_cspace, cache_size, pmem);
if (pcssepr->map == 0) {
diff --git a/gs/src/gscspace.c b/gs/src/gscspace.c
index b445953fe..d36e3b83c 100644
--- a/gs/src/gscspace.c
+++ b/gs/src/gscspace.c
@@ -77,28 +77,37 @@ gs_cspace_DeviceCMYK(const gs_imager_state * pis)
/* ------ Create/copy/destroy ------ */
-private int
-cspace_build(gs_color_space ** ppcspace, const gs_color_space_type * pcstype,
- gs_memory_t * pmem)
-{
- cs_alloc(*ppcspace, pcstype, pmem);
+int
+gs_cspace_alloc(gs_color_space ** ppcspace,
+ const gs_color_space_type * pcstype,
+ gs_memory_t * mem)
+{
+ gs_color_space *pcspace =
+ gs_alloc_struct(mem, gs_color_space, &st_color_space,
+ "gs_cspace_alloc");
+
+ if (pcspace == 0)
+ return_error(gs_error_VMerror);
+ pcspace->pmem = mem;
+ pcspace->type = pcstype;
+ *ppcspace = pcspace;
return 0;
}
int
gs_cspace_build_DeviceGray(gs_color_space ** ppcspace, gs_memory_t * pmem)
{
- return cspace_build(ppcspace, &gs_color_space_type_DeviceGray, pmem);
+ return gs_cspace_alloc(ppcspace, &gs_color_space_type_DeviceGray, pmem);
}
int
gs_cspace_build_DeviceRGB(gs_color_space ** ppcspace, gs_memory_t * pmem)
{
- return cspace_build(ppcspace, &gs_color_space_type_DeviceRGB, pmem);
+ return gs_cspace_alloc(ppcspace, &gs_color_space_type_DeviceRGB, pmem);
}
int
gs_cspace_build_DeviceCMYK(gs_color_space ** ppcspace, gs_memory_t * pmem)
{
- return cspace_build(ppcspace, &gs_color_space_type_DeviceCMYK, pmem);
+ return gs_cspace_alloc(ppcspace, &gs_color_space_type_DeviceCMYK, pmem);
}
/*
@@ -107,8 +116,11 @@ gs_cspace_build_DeviceCMYK(gs_color_space ** ppcspace, gs_memory_t * pmem)
* compound color space when legal, but it can't check that the operation is
* actually legal.
*/
-#define cs_copy(pcsto, pcsfrom)\
- memcpy(pcsto, pcsfrom, (pcsfrom)->type->stype->ssize)
+inline private void
+cs_copy(gs_color_space *pcsto, const gs_color_space *pcsfrom)
+{
+ memcpy(pcsto, pcsfrom, pcsfrom->type->stype->ssize);
+}
/* Copy a color space into one newly allocated by the caller. */
void
diff --git a/gs/src/gsmalloc.c b/gs/src/gsmalloc.c
index 0bc2394a1..1f9127412 100644
--- a/gs/src/gsmalloc.c
+++ b/gs/src/gsmalloc.c
@@ -60,6 +60,7 @@ private const gs_memory_procs_t gs_malloc_memory_procs =
gs_heap_free_object,
gs_heap_status,
gs_heap_free_all,
+ gs_ignore_consolidate_free,
/* Object memory procedures */
gs_heap_alloc_bytes,
gs_heap_alloc_struct,
diff --git a/gs/src/gsmemlok.c b/gs/src/gsmemlok.c
index 21cf9c629..e70c1df22 100644
--- a/gs/src/gsmemlok.c
+++ b/gs/src/gsmemlok.c
@@ -33,6 +33,7 @@ private gs_memory_proc_resize_object(gs_locked_resize_object);
private gs_memory_proc_free_object(gs_locked_free_object);
private gs_memory_proc_status(gs_locked_status);
private gs_memory_proc_free_all(gs_locked_free_all);
+private gs_memory_proc_consolidate_free(gs_locked_consolidate_free);
/* Object memory procedures */
private gs_memory_proc_alloc_bytes(gs_locked_alloc_bytes);
@@ -59,6 +60,7 @@ private gs_memory_procs_t locked_procs =
gs_locked_free_object,
gs_locked_status,
gs_locked_free_all,
+ gs_locked_consolidate_free,
/* Object memory procedures */
gs_locked_alloc_bytes,
gs_locked_alloc_struct,
@@ -149,6 +151,13 @@ gs_locked_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname)
if (free_mask & FREE_ALL_ALLOCATOR)
gs_free_object(target, lmem, cname);
}
+private void
+gs_locked_consolidate_free(gs_memory_t * mem)
+{
+ DO_MONITORED(
+ (*lmem->target->procs.consolidate_free)(lmem->target)
+ );
+}
private byte *
gs_locked_alloc_bytes(gs_memory_t * mem, uint size, client_name_t cname)
{
diff --git a/gs/src/gsmemory.c b/gs/src/gsmemory.c
index 01c133d1d..6d5186931 100644
--- a/gs/src/gsmemory.c
+++ b/gs/src/gsmemory.c
@@ -80,6 +80,12 @@ gs_ignore_free_string(gs_memory_t * mem, byte * data, uint nbytes,
{
}
+/* No-op consolidation procedure */
+void
+gs_ignore_consolidate_free(gs_memory_t *mem)
+{
+}
+
/* No-op pointer enumeration procedure */
ENUM_PTRS_BEGIN_PROC(gs_no_struct_enum_ptrs)
{
diff --git a/gs/src/gsmemory.h b/gs/src/gsmemory.h
index 5e8036ef7..de0ed9813 100644
--- a/gs/src/gsmemory.h
+++ b/gs/src/gsmemory.h
@@ -84,6 +84,8 @@ typedef struct gs_memory_procs_s {
gs_memory_t_proc_status(proc, gs_memory_t)
#define gs_memory_proc_free_all(proc)\
gs_memory_t_proc_free_all(proc, gs_memory_t)
+#define gs_memory_proc_consolidate_free(proc)\
+ gs_memory_t_proc_consolidate_free(proc, gs_memory_t)
/*
* Allocate possibly movable bytes. (We inherit allocating immovable
@@ -243,6 +245,9 @@ int gs_register_struct_root(P4(gs_memory_t *mem, gs_gc_root_t *root,
gs_memory_proc_free_object(gs_ignore_free_object);
gs_memory_proc_free_string(gs_ignore_free_string);
+/* Define a no-op consolidation procedure. */
+gs_memory_proc_consolidate_free(gs_ignore_consolidate_free);
+
/*
* Allocate a structure using a "raw memory" allocator. Note that this does
* not retain the identity of the structure. Note also that it returns a
diff --git a/gs/src/gsmemraw.h b/gs/src/gsmemraw.h
index 26eacfded..fc57133a6 100644
--- a/gs/src/gsmemraw.h
+++ b/gs/src/gsmemraw.h
@@ -133,18 +133,31 @@ typedef struct gs_raw_memory_s gs_raw_memory_t;
void proc(P3(mem_t *mem, uint free_mask, client_name_t cname))
#define gs_memory_free_all(mem, free_mask, cname)\
- (*(mem)->procs.free_all)(mem, free_mask, cname)
+ ((mem)->procs.free_all(mem, free_mask, cname))
/* Backward compatibility */
#define gs_free_all(mem)\
gs_memory_free_all(mem, FREE_ALL_DATA, "(free_all)")
+ /*
+ * Consolidate free space. This may be used as part of (or
+ * as an alternative to) garbage collection, or before
+ * giving up on an attempt to allocate.
+ */
+
+#define gs_memory_t_proc_consolidate_free(proc, mem_t)\
+ void proc(P1(mem_t *mem))
+
+#define gs_consolidate_free(mem)\
+ ((mem)->procs.consolidate_free(mem))
+
/* Define the members of the procedure structure. */
#define gs_raw_memory_procs(mem_t)\
gs_memory_t_proc_alloc_bytes((*alloc_bytes_immovable), mem_t);\
gs_memory_t_proc_resize_object((*resize_object), mem_t);\
gs_memory_t_proc_free_object((*free_object), mem_t);\
gs_memory_t_proc_status((*status), mem_t);\
- gs_memory_t_proc_free_all((*free_all), mem_t)
+ gs_memory_t_proc_free_all((*free_all), mem_t);\
+ gs_memory_t_proc_consolidate_free((*consolidate_free), mem_t)
/* Define the procedure vector for a raw memory allocator. */
typedef struct gs_raw_memory_procs_s {
diff --git a/gs/src/gsnogc.c b/gs/src/gsnogc.c
index 029717c19..7ff6b4ddd 100644
--- a/gs/src/gsnogc.c
+++ b/gs/src/gsnogc.c
@@ -228,6 +228,24 @@ sf_merge_strings(chunk_t * cp)
}
}
+/* Consolidate free space. */
+private void
+sf_consolidate_free(gs_memory_t *mem)
+{
+ gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
+ chunk_t *cp;
+
+ for (cp = imem->clast; cp != 0; cp = cp->cprev) {
+ byte *top = cp->ctop;
+
+ sf_merge_strings(cp);
+ imem->lost.strings -= cp->ctop - top;
+ }
+
+ /* Merge free objects, detecting entirely free chunks. */
+ ialloc_consolidate_free(imem);
+}
+
/*
* This procedure has the same API as the garbage collector used by the
* PostScript interpreter, but it is designed to be used in environments
@@ -245,20 +263,10 @@ gs_reclaim(vm_spaces * pspaces, bool global)
for (space = 0; space < countof(pspaces->indexed); ++space) {
gs_ref_memory_t *mem = pspaces->indexed[space];
- chunk_t *cp;
- chunk_t *cprev;
-
- /*
- * We're going to recompute lost.objects, by subtracting the
- * amount of space reclaimed minus the amount of that space that
- * was on free lists.
- */
- ulong found = 0;
if (mem == 0 || mem == mem_prev)
continue;
mem_prev = mem;
- alloc_close_chunk(mem);
/*
* Change the allocator to use string freelists in the future.
@@ -267,69 +275,9 @@ gs_reclaim(vm_spaces * pspaces, bool global)
if (mem->procs.free_string != gs_ignore_free_string)
mem->procs.free_string = sf_free_string;
mem->procs.enable_free = sf_enable_free;
+ mem->procs.consolidate_free = sf_consolidate_free;
- /* Visit chunks in reverse order to encourage LIFO behavior. */
- for (cp = mem->clast; cp != 0; cp = cprev) {
- obj_header_t *begin_free = (obj_header_t *) cp->cbase;
-
- cprev = cp->cprev;
- SCAN_CHUNK_OBJECTS(cp)
- DO_ALL
- if (pre->o_type == &st_free) {
- if (begin_free == 0)
- begin_free = pre;
- } else
- begin_free = 0;
- END_OBJECTS_SCAN
- if (!begin_free)
- continue;
- /* We found free objects at the top of the object area. */
- found += (byte *) cp->cbot - (byte *) begin_free;
- /* Remove the free objects from the freelists. */
- {
- int i;
-
- for (i = 0; i < num_freelists; i++) {
- obj_header_t *pfree;
- obj_header_t **ppfprev = &mem->freelists[i];
- uint free_size =
- (i << log2_obj_align_mod) + sizeof(obj_header_t);
-
- while ((pfree = *ppfprev) != 0)
- if (ptr_ge(pfree, begin_free) &&
- ptr_lt(pfree, cp->cbot)
- ) { /* We're removing an object. */
- *ppfprev = *(obj_header_t **) pfree;
- found -= free_size;
- } else
- ppfprev = (obj_header_t **) pfree;
- }
- }
- {
- byte *top = cp->ctop;
-
- sf_merge_strings(cp);
- mem->lost.strings -= cp->ctop - top;
- }
- if (begin_free == (obj_header_t *) cp->cbase &&
- cp->ctop == cp->climit
- ) { /* The entire chunk is free. */
- chunk_t *cnext = cp->cnext;
-
- alloc_free_chunk(cp, mem);
- if (mem->pcc == cp)
- mem->pcc =
- (cnext == 0 ? cprev : cprev == 0 ? cnext :
- cprev->cbot - cprev->ctop > cnext->cbot - cnext->ctop ?
- cprev : cnext);
- } else {
- if_debug4('a', "[a]resetting chunk 0x%lx cbot from 0x%lx to 0x%lx (%lu free)\n",
- (ulong) cp, (ulong) cp->cbot, (ulong) begin_free,
- (ulong) ((byte *) cp->cbot - (byte *) begin_free));
- cp->cbot = (byte *) begin_free;
- }
- }
- mem->lost.objects -= found;
- alloc_open_chunk(mem);
+ /* Merge free objects, detecting entirely free chunks. */
+ gs_consolidate_free((gs_memory_t *)mem);
}
}
diff --git a/gs/src/gsparam.c b/gs/src/gsparam.c
index f03d1673a..6a99700ee 100644
--- a/gs/src/gsparam.c
+++ b/gs/src/gsparam.c
@@ -33,8 +33,9 @@ param_init_enumerator(gs_param_enumerator_t * enumerator)
}
/* Transfer a collection of parameters. */
-private const byte xfer_item_sizes[] =
-{GS_PARAM_TYPE_SIZES(0)};
+private const byte xfer_item_sizes[] = {
+ GS_PARAM_TYPE_SIZES(0)
+};
int
gs_param_read_items(gs_param_list * plist, void *obj,
const gs_param_item_t * items)
@@ -103,7 +104,8 @@ param_coerce_typed(gs_param_typed_value * pvalue, gs_param_type req_type,
/*
* Look for coercion opportunities. It would be wonderful if we
* could convert int/float arrays and name/string arrays, but
- * right now we can't.
+ * right now we can't. However, a 0-length heterogenous array
+ * will satisfy a request for any specific type.
*/
switch (pvalue->type /* actual type */ ) {
case gs_param_type_int:
@@ -174,6 +176,15 @@ param_coerce_typed(gs_param_typed_value * pvalue, gs_param_type req_type,
if (req_type == gs_param_type_string_array)
goto ok;
break;
+ case gs_param_type_array:
+ if (pvalue->value.d.size == 0 &&
+ (req_type == gs_param_type_int_array ||
+ req_type == gs_param_type_float_array ||
+ req_type == gs_param_type_string_array ||
+ req_type == gs_param_type_name_array)
+ )
+ goto ok;
+ break;
default:
break;
}
diff --git a/gs/src/gspcolor.c b/gs/src/gspcolor.c
index 68b9f32af..137d9970f 100644
--- a/gs/src/gspcolor.c
+++ b/gs/src/gspcolor.c
@@ -80,12 +80,15 @@ gs_cspace_build_Pattern1(gs_color_space ** ppcspace,
const gs_color_space * pbase_cspace, gs_memory_t * pmem)
{
gs_color_space *pcspace = 0;
+ int code;
if (pbase_cspace != 0) {
if (gs_color_space_num_components(pcspace) < 0) /* Pattern space */
return_error(gs_error_rangecheck);
}
- cs_alloc(pcspace, &gs_color_space_type_Pattern, pmem);
+ code = gs_cspace_alloc(&pcspace, &gs_color_space_type_Pattern, pmem);
+ if (code < 0)
+ return code;
if (pbase_cspace != 0) {
pcspace->params.pattern.has_base_space = true;
gs_cspace_init_from((gs_color_space *) & (pcspace->params.pattern.base_space),
diff --git a/gs/src/gsstate.c b/gs/src/gsstate.c
index 79b342c70..00c709f7b 100644
--- a/gs/src/gsstate.c
+++ b/gs/src/gsstate.c
@@ -237,6 +237,27 @@ null_transfer(floatp gray, const gx_transfer_map * pmap)
{
return gray;
}
+private void
+rc_free_imager_shared(gs_memory_t * mem, void *data, client_name_t cname)
+{
+ gs_imager_state_shared_t * const shared =
+ ((gs_imager_state *)data)->shared;
+
+ if (shared->cs_DeviceCMYK) {
+ gs_cspace_release(shared->cs_DeviceCMYK);
+ gs_free_object(mem, shared->cs_DeviceCMYK, "shared DeviceCMYK");
+ }
+ if (shared->cs_DeviceRGB) {
+ gs_cspace_release(shared->cs_DeviceRGB);
+ gs_free_object(mem, shared->cs_DeviceRGB, "shared DeviceRGB");
+ }
+ if (shared->cs_DeviceGray) {
+ gs_cspace_release(shared->cs_DeviceGray);
+ gs_free_object(mem, shared->cs_DeviceGray, "shared DeviceGray");
+ }
+ rc_free_struct_only(mem, data, cname);
+}
+
int
gs_imager_state_initialize(gs_imager_state * pis, gs_memory_t * mem)
{
@@ -250,12 +271,17 @@ gs_imager_state_initialize(gs_imager_state * pis, gs_memory_t * mem)
&st_imager_state_shared, mem,
return_error(gs_error_VMerror),
"gs_imager_state_init(shared)");
- pis->shared = shared;
+ shared->cs_DeviceGray = shared->cs_DeviceRGB =
+ shared->cs_DeviceCMYK = 0; /* in case we bail out */
+ shared->rc.free = rc_free_imager_shared;
if ((code = gs_cspace_build_DeviceGray(&shared->cs_DeviceGray, mem)) < 0 ||
- (code = gs_cspace_build_DeviceRGB(&shared->cs_DeviceRGB, mem)) < 0 ||
- (code = gs_cspace_build_DeviceCMYK(&shared->cs_DeviceCMYK, mem)) < 0
- )
+ (code = gs_cspace_build_DeviceRGB(&shared->cs_DeviceRGB, mem)) < 0 ||
+ (code = gs_cspace_build_DeviceCMYK(&shared->cs_DeviceCMYK, mem)) < 0
+ ) {
+ rc_free_imager_shared(mem, shared, "gs_imager_state_init(shared)");
return code;
+ }
+ pis->shared = shared;
}
/* Skip halftone */
{
diff --git a/gs/src/gxalloc.h b/gs/src/gxalloc.h
index e076eb814..ae0c2a056 100644
--- a/gs/src/gxalloc.h
+++ b/gs/src/gxalloc.h
@@ -317,31 +317,33 @@ struct gs_ref_memory_s {
gs_raw_memory_t *parent; /* for allocating chunks */
uint chunk_size;
uint large_size; /* min size to give large object */
- /* its own chunk: must be */
- /* 1 mod obj_align_mod */
+ /* its own chunk: must be */
+ /* 1 mod obj_align_mod */
gs_ref_memory_t *global; /* global VM for this allocator */
- /* (may point to itself) */
+ /* (may point to itself) */
uint space; /* a_local, a_global, a_system */
/* Callers can change the following dynamically */
/* (through a procedural interface). */
gs_memory_gc_status_t gc_status;
/* The following are updated dynamically. */
+ bool is_controlled; /* if true, this allocator doesn't manage */
+ /* its own chunks */
ulong limit; /* signal a VMerror when total */
- /* allocated exceeds this */
+ /* allocated exceeds this */
chunk_t *cfirst; /* head of chunk list */
chunk_t *clast; /* tail of chunk list */
chunk_t cc; /* current chunk */
chunk_t *pcc; /* where to store cc */
chunk_locator_t cfreed; /* chunk where last object freed */
ulong allocated; /* total size of all chunks */
- /* allocated at this save level */
+ /* allocated at this save level */
long inherited; /* chunks allocated at outer save */
- /* levels that should be counted */
- /* towards the GC threshold */
- /* (may be negative, but allocated + */
- /* inherited >= 0 always) */
+ /* levels that should be counted */
+ /* towards the GC threshold */
+ /* (may be negative, but allocated + */
+ /* inherited >= 0 always) */
ulong gc_allocated; /* value of (allocated + */
- /* previous_status.allocated) after last GC */
+ /* previous_status.allocated) after last GC */
struct lost_ { /* space freed and 'lost' */
ulong objects;
ulong refs;
@@ -360,9 +362,9 @@ struct gs_ref_memory_s {
struct alloc_save_s *saved;
struct alloc_save_s *reloc_saved; /* for GC */
gs_memory_status_t previous_status; /* total allocated & used */
- /* in outer save levels */
- /* We put the freelists last to keep the scalar */
- /* offsets small. */
+ /* in outer save levels */
+ /* We put the freelists last to keep the */
+ /* scalar offsets small. */
obj_header_t *freelists[num_freelists];
};
diff --git a/gs/src/gxclip2.c b/gs/src/gxclip2.c
index 8897ee4d4..6b4274a29 100644
--- a/gs/src/gxclip2.c
+++ b/gs/src/gxclip2.c
@@ -221,7 +221,8 @@ tile_clip_copy_mono(gx_device * dev,
tx1 = tx;\
do {\
t_next(tx);\
- } while ( tx < x + w && (*tp & tbit) != 0 );
+ } while ( tx < x + w && (*tp & tbit) != 0 );\
+ if_debug3('T', "[T]run x=(%d,%d), y=%d\n", tx1, tx, ty);
/* (body goes here) */
#define END_FOR_RUNS()\
}\
diff --git a/gs/src/gxcspace.h b/gs/src/gxcspace.h
index ddf43403e..3f32b7d8d 100644
--- a/gs/src/gxcspace.h
+++ b/gs/src/gxcspace.h
@@ -228,22 +228,12 @@ extern const gs_color_space_type
extern_st(st_color_space);
/*
- * Macros for allocating, initializing, and freeing color spaces.
- * These are only used by color space implementations.
+ * Allocate a color space and initialize its type and memory fields.
+ * This is only used by color space implementations.
*/
-#define cs_alloc(pcspace, pcstype, pmemory)\
- BEGIN\
- (pcspace) = gs_alloc_struct(pmemory, gs_color_space, &st_color_space,\
- "cs_alloc");\
- if ((pcspace) == 0)\
- return_error(gs_error_VMerror);\
- (pcspace)->pmem = (pmemory);\
- (pcspace)->type = (pcstype);\
- END
-
-#define cs_undo_alloc(pcspace)\
- (gs_free_object((pcspace)->pmem, pcspace, "cs_undo_alloc"),\
- gs_note_error(gs_error_VMerror))
+int gs_cspace_alloc(P3(gs_color_space **ppcspace,
+ const gs_color_space_type *pcstype,
+ gs_memory_t *mem));
#endif /* gxcspace_INCLUDED */
diff --git a/gs/src/gxp1fill.c b/gs/src/gxp1fill.c
index 08645dcdd..5cce33624 100644
--- a/gs/src/gxp1fill.c
+++ b/gs/src/gxp1fill.c
@@ -102,6 +102,8 @@ tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0,
{
gs_rect bbox; /* bounding box in device space */
gs_rect ibbox; /* bounding box in stepping space */
+ double bbw = ptile->bbox.q.x - ptile->bbox.p.x;
+ double bbh = ptile->bbox.q.y - ptile->bbox.p.y;
bbox.p.x = x0, bbox.p.y = y0;
bbox.q.x = x1, bbox.q.y = y1;
@@ -111,14 +113,14 @@ tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0,
x0, y0, w0, h0,
ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y,
step_matrix.tx, step_matrix.ty);
- i0 = (int)floor(ibbox.p.x - ptile->bbox.q.x + 0.000001);
- i1 = (int)ceil(ibbox.q.x - ptile->bbox.p.x - 0.000001);
- j0 = (int)floor(ibbox.p.y - ptile->bbox.q.y + 0.000001);
- j1 = (int)ceil(ibbox.q.y - ptile->bbox.p.y - 0.000001);
+ i0 = (int)ceil(ibbox.p.x - bbw - 0.000001);
+ i1 = (int)floor(ibbox.q.x + 0.000001);
+ j0 = (int)ceil(ibbox.p.y - bbh - 0.000001);
+ j1 = (int)floor(ibbox.q.y + 0.000001);
}
if_debug4('T', "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1);
- for (i = i0; i < i1; i++)
- for (j = j0; j < j1; j++) {
+ for (i = i0; i <= i1; i++)
+ for (j = j0; j <= j1; j++) {
int x = (int)(step_matrix.xx * i +
step_matrix.yx * j + step_matrix.tx);
int y = (int)(step_matrix.xy * i +
@@ -140,13 +142,13 @@ tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0,
w = x1 - x;
if (y + h > y1)
h = y1 - y;
- if_debug4('T', "=>(%d,%d) w,h=(%d,%d)\n",
- x, y, w, h);
+ if_debug6('T', "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n",
+ x, y, w, h, xoff, yoff);
if (w > 0 && h > 0) {
if (ptfs->pcdev == (gx_device *) & ptfs->cdev)
tile_clip_set_phase(&ptfs->cdev,
- imod(xoff - x, ptfs->tmask->rep_width),
- imod(yoff - y, ptfs->tmask->rep_height));
+ imod(xoff - x, ptfs->tmask->rep_width),
+ imod(yoff - y, ptfs->tmask->rep_height));
/* Set the offsets for colored pattern fills */
ptfs->xoff = xoff;
ptfs->yoff = yoff;
diff --git a/gs/src/iparam.c b/gs/src/iparam.c
index f9e76722a..2cd23498b 100644
--- a/gs/src/iparam.c
+++ b/gs/src/iparam.c
@@ -688,8 +688,10 @@ ref_param_read_typed(gs_param_list * plist, gs_param_name pkey,
iparam_check_read(loc);
if (r_size(loc.pvalue) <= 0) {
/* 0-length array; can't get type info */
- pvalue->type = gs_param_type_int_array;
- return ref_param_read_int_array(plist, pkey, &pvalue->value.ia);
+ pvalue->type = gs_param_type_array;
+ pvalue->value.d.list = 0;
+ pvalue->value.d.size = 0;
+ return 0;
}
/* Get array type based on type of 1st element of array */
array_get(loc.pvalue, 0, &elt);
diff --git a/gs/src/version.mak b/gs/src/version.mak
index 6e16f346b..00b66bf0e 100644
--- a/gs/src/version.mak
+++ b/gs/src/version.mak
@@ -24,10 +24,10 @@ VERSION_MAK=$(GLSRC)version.mak
# Major and minor version numbers.
# MINOR0 is different from MINOR only if MINOR is a single digit.
GS_VERSION_MAJOR=5
-GS_VERSION_MINOR=37
-GS_VERSION_MINOR0=37
+GS_VERSION_MINOR=38
+GS_VERSION_MINOR0=38
# Revision date: year x 10000 + month x 100 + day.
-GS_REVISIONDATE=19980831
+GS_REVISIONDATE=19980903
# Derived values
GS_VERSION=$(GS_VERSION_MAJOR)$(GS_VERSION_MINOR0)
diff --git a/gs/src/zfileio.c b/gs/src/zfileio.c
index 951b6b1f2..ac51265bd 100644
--- a/gs/src/zfileio.c
+++ b/gs/src/zfileio.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -813,7 +813,7 @@ handle_read_status(int ch, const ref * fop, const uint * pindex,
/* Handle an exceptional status return from a write stream. */
/* fop points to the ref for the stream. */
/* ch may be any stream exceptional value. */
-/* Return 0, o_push_estack, or an error. */
+/* Return 0, 1 (EOF), o_push_estack, or an error. */
private int
handle_write_status(int ch, const ref * fop, const uint * pindex,
int (*cont) (P1(os_ptr)))
@@ -821,6 +821,8 @@ handle_write_status(int ch, const ref * fop, const uint * pindex,
switch (ch) {
default: /* error */
return_error(e_ioerror);
+ case EOFC:
+ return 1;
case INTC:
case CALLC:
if (pindex) {