[gs-cvs] rev 8369 - trunk/gs/src

leonardo at ghostscript.com leonardo at ghostscript.com
Wed Nov 14 23:22:43 PST 2007


Author: leonardo
Date: 2007-11-14 23:22:43 -0800 (Wed, 14 Nov 2007)
New Revision: 8369

Modified:
   trunk/gs/src/gxcldev.h
   trunk/gs/src/gxclist.c
   trunk/gs/src/gxclist.h
   trunk/gs/src/gxclpage.c
   trunk/gs/src/gxclrast.c
   trunk/gs/src/gxclread.c
   trunk/gs/src/gxclutil.c
   trunk/gs/src/gxp1fill.c
Log:
Fix (clist) : Providing clist instruction ids and offsets to debug trace (continued).

DETAILS :

The last patch appears incorrect for the debug build 
and causes crashes sometimes. Not sure why local testing didn't detect that.

This change is algorithmically equivalent for release build.
In the debug build it fixes problems of the last patch.

1. Offset map could be prematurely released by the garbager
(It could cause a crash. Not sure why the local test didn't detect it).
A new pointer gx_device_clist_reader::offset_map prevents that.
Added it to the garbager descriptor and provided its initialization.

2. buffer_segment_index can fail with returning a negative index.
Checked that and propagated error codes.

4. Besides top_up_cbuf, the buffer topping up also happens 
with calling memmove when reading bitmap data. 
Added calls to top_up_offset_map for accounting that.

5. See comment in top_up_offset_map about the improved invariant.

6. The prototupe of top_up_cbuf is changed with passing the error code.
Due to that the variable 'cbp' is droped the 'register' modifier.
We believe it won't cause a visible slowdown because
modern compilers are smart enough.

7. Do not maintain offset_map when -ZL is not specified.
It saves some CPU time with debug build.

EXPECTED DIFFERENCES :

None.


Modified: trunk/gs/src/gxcldev.h
===================================================================
--- trunk/gs/src/gxcldev.h	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxcldev.h	2007-11-15 07:22:43 UTC (rev 8369)
@@ -715,7 +715,7 @@
 			  int band_first, int band_last, int x0, int y0);
 #ifdef DEBUG 
 int64_t clist_file_offset(const stream_state *st, uint buffer_offset);
-void top_up_offset_map(stream_state * st, const byte *buf, const byte *ptr, const byte *end);
+int top_up_offset_map(stream_state * st, const byte *buf, const byte *ptr, const byte *end);
 #endif
 
 #endif /* gxcldev_INCLUDED */

Modified: trunk/gs/src/gxclist.c
===================================================================
--- trunk/gs/src/gxclist.c	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxclist.c	2007-11-15 07:22:43 UTC (rev 8369)
@@ -59,7 +59,9 @@
          */
         if (index == 0)
             return ENUM_OBJ(cdev->reader.band_complexity_array);
-        else
+        else if (index == 1)
+	    return ENUM_OBJ(cdev->reader.offset_map);
+	else
             return 0;
     }
 ENUM_PTRS_END
@@ -75,13 +77,14 @@
 	RELOC_VAR(cdev->writer.pinst);
         RELOC_USING(st_imager_state, &cdev->writer.imager_state,
             sizeof(gs_imager_state));
-    }
-    else
+    } else {
         /* 041207
          * clist is reader.
          * See note above in ENUM_PTRS_WITH section.
          */
         RELOC_VAR(cdev->reader.band_complexity_array);
+        RELOC_VAR(cdev->reader.offset_map);
+    }
 } RELOC_PTRS_END
 public_st_device_clist();
 

Modified: trunk/gs/src/gxclist.h
===================================================================
--- trunk/gs/src/gxclist.h	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxclist.h	2007-11-15 07:22:43 UTC (rev 8369)
@@ -239,18 +239,18 @@
     gs_id device_halftone_id;	/* id of device halftone */
     gs_id image_enum_id;	/* non-0 if we are inside an image */
 				/* that we are passing through */
-	int error_is_retryable;		/* Extra status used to distinguish hard VMerrors */
-	                           /* from warnings upgraded to VMerrors. */
-	                           /* T if err ret'd by cmd_put_op et al can be retried */
-	int permanent_error;		/* if < 0, error only cleared by clist_reset() */
-	int driver_call_nesting;	/* nesting level of non-retryable driver calls */
-	int ignore_lo_mem_warnings;	/* ignore warnings from clist file/mem */
-		/* Following must be set before writing */
-	proc_free_up_bandlist_memory((*free_up_bandlist_memory)); /* if nz, proc to free some bandlist memory */
-	int disable_mask;		/* mask of routines to disable clist_disable_xxx */
-	gs_pattern1_instance_t *pinst; /* Used when it is a pattern clist. */
-	bool cropping_by_path;
-	int cropping_min, cropping_max;
+    int error_is_retryable;		/* Extra status used to distinguish hard VMerrors */
+			       /* from warnings upgraded to VMerrors. */
+			       /* T if err ret'd by cmd_put_op et al can be retried */
+    int permanent_error;		/* if < 0, error only cleared by clist_reset() */
+    int driver_call_nesting;	/* nesting level of non-retryable driver calls */
+    int ignore_lo_mem_warnings;	/* ignore warnings from clist file/mem */
+	    /* Following must be set before writing */
+    proc_free_up_bandlist_memory((*free_up_bandlist_memory)); /* if nz, proc to free some bandlist memory */
+    int disable_mask;		/* mask of routines to disable clist_disable_xxx */
+    gs_pattern1_instance_t *pinst; /* Used when it is a pattern clist. */
+    bool cropping_by_path;
+    int cropping_min, cropping_max;
     ulong ins_count;
 } gx_device_clist_writer;
 
@@ -272,6 +272,7 @@
     const gx_placed_page *pages;
     int num_pages;
     gx_band_complexity_t *band_complexity_array;  /* num_bands elements */
+    void *offset_map; /* Just against collecting the map as garbage. */
 } gx_device_clist_reader;
 
 union gx_device_clist_s {

Modified: trunk/gs/src/gxclpage.c
===================================================================
--- trunk/gs/src/gxclpage.c	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxclpage.c	2007-11-15 07:22:43 UTC (rev 8369)
@@ -99,6 +99,7 @@
     pcldev->ymin = pcldev->ymax = 0;
     pcldev->pages = ppages;
     pcldev->num_pages = count;
+    pcldev->offset_map = NULL;
     /* Render the pages. */
     {
 	int code = (*dev_proc(pdev, output_page))

Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxclrast.c	2007-11-15 07:22:43 UTC (rev 8369)
@@ -143,19 +143,28 @@
 }
 
 /* Read more data into a command buffer. */
-static const byte *
-top_up_cbuf(command_buf_t *pcb, const byte *cbp)
+static int
+top_up_cbuf(command_buf_t *pcb, const byte **pcbp)
 {
     uint nread;
+    const byte *cbp = *pcbp;
     byte *cb_top = pcb->data + (pcb->end - cbp);
+#   ifdef DEBUG
+    stream_state *st = pcb->s->state;
+#   endif
 
     if (seofp(pcb->s)) {
 	/* Can't use offset_map, because s_close resets s->state. Don't top up. */
 	pcb->end_status = pcb->s->end_status;
-	return cbp;
+	return 0;
     }
 #   ifdef DEBUG
-	top_up_offset_map(pcb->s->state, pcb->data, cbp, pcb->end);
+    {
+	int code = top_up_offset_map(st, pcb->data, cbp, pcb->end);
+
+	if (code < 0)
+	    return code;
+    }
 #   endif
     memmove(pcb->data, cbp, pcb->end - cbp);
     nread = pcb->end - cb_top;
@@ -167,7 +176,8 @@
     }
     set_cb_end(pcb, cb_top + nread);
     process_interrupts(pcb->s->memory);
-    return pcb->data;
+    *pcbp = pcb->data;
+    return 0;
 }
 
 /* Read data from the command buffer and stream. */
@@ -268,7 +278,7 @@
     /* must be aligned */
 #define data_bits_size cbuf_size
     byte *data_bits = 0;
-    register const byte *cbp;
+    const byte *cbp;
     int dev_depth;		/* May vary due to compositing devices */
     int dev_depth_bytes;
     int odd_delta_shift;
@@ -407,7 +417,9 @@
 		    break;
 		}
 	    } else {
-		cbp = top_up_cbuf(&cbuf, cbp);
+		code = top_up_cbuf(&cbuf, &cbp);
+		if (code < 0)
+		    return code;
 	    }
 	}
 	op = *cbp++;
@@ -782,9 +794,14 @@
 			/* the uncompressed size. */
 			uint cleft = cbuf.end - cbp;
 
-			if (cleft < bytes) {
+			if (cleft < bytes  && !cbuf.end_status) {
 			    uint nread = cbuf_size - cleft;
 
+#			    ifdef DEBUG
+				code = top_up_offset_map(st, cbuf.data, cbp, cbuf.end);
+				if (code < 0)
+				    return code;
+#			    endif
 			    memmove(cbuf.data, cbp, cleft);
 			    cbuf.end_status = sgets(s, cbuf.data + cleft, nread, &nread);
 			    set_cb_end(&cbuf, cbuf.data + cleft + nread);
@@ -1116,7 +1133,9 @@
 				if (flags & 1) {
 				    if (cbuf.end - cbp <
 					2 * cmd_max_intsize(sizeof(uint)))
-					cbp = top_up_cbuf(&cbuf, cbp);
+					code = top_up_cbuf(&cbuf, &cbp);
+					if (code < 0)
+					    return code;
 				    cmd_getw(planes[plane].raster, cbp);
 				    if ((raster1 = planes[plane].raster) != 0)
 					cmd_getw(data_x, cbp);
@@ -1162,7 +1181,9 @@
 			data_size *= data_height;
 			data_on_heap = 0;
 			if (cbuf.end - cbp < data_size)
-			    cbp = top_up_cbuf(&cbuf, cbp);
+			    code = top_up_cbuf(&cbuf, &cbp);
+			    if (code < 0)
+				return code;
 			if (cbuf.end - cbp >= data_size) {
 			    planes[0].data = cbp;
 			    cbp += data_size;
@@ -1289,8 +1310,11 @@
 					goto out;
 				    }
 				    enc_u_getw(color_size, cbp);
-				    if (cbp + color_size > cbuf.limit)
-					cbp = top_up_cbuf(&cbuf, cbp);
+				    if (cbp + color_size > cbuf.limit) {
+					code = top_up_cbuf(&cbuf, &cbp);
+					if (code < 0)
+					    return code;
+				    }
 				    code = pdct->read(&dev_color, &imager_state,
 						      &dev_color, tdev, cbp,
 						      color_size, mem);
@@ -1472,8 +1496,11 @@
 				    gs_fixed_rect clip;
 				    fixed hh = int2fixed(swap_axes ? target->width : target->height);
 
-				    if (cbuf.end - cbp < 5 * cmd_max_intsize(sizeof(frac31)))
-					cbp = top_up_cbuf(&cbuf, cbp);
+				    if (cbuf.end - cbp < 5 * cmd_max_intsize(sizeof(frac31))) {
+					code = top_up_cbuf(&cbuf, &cbp);
+					if (code < 0)
+					    return code;
+				    }
 				    cmd_getw(clip.p.x, cbp);
 				    cmd_getw(clip.p.y, cbp);
 				    cmd_getw(clip.q.x, cbp);
@@ -1495,8 +1522,11 @@
 				    cmd_getw(colors_mask, cbp);
 				    for (i = 0; i < 4; i++, m <<= 1) {
 					if (colors_mask & m) {
-					    if (cbuf.end - cbp < num_components * cmd_max_intsize(sizeof(frac31)))
-						cbp = top_up_cbuf(&cbuf, cbp);
+					    if (cbuf.end - cbp < num_components * cmd_max_intsize(sizeof(frac31))) {
+						code = top_up_cbuf(&cbuf, &cbp);
+						if (code < 0)
+						    return code;
+					    }
 					    cc[i] = c[i];
 					    for (j = 0; j < num_components; j++)
 						cmd_getfrac(c[i][j], cbp);
@@ -1802,9 +1832,18 @@
 	 */
 	uint cleft = pcb->end - cbp;
 
-	if (cleft < bytes) {
+	if (cleft < bytes && !pcb->end_status) {
 	    uint nread = cbuf_size - cleft;
+	    stream_state *st = pcb->s->state;
 
+#	    ifdef DEBUG
+	    {
+		int code = top_up_offset_map(st, pcb->data, cbp, pcb->end);
+
+		if (code < 0)
+		    return code;
+	    }
+#	    endif
 	    memmove(pcb->data, cbp, cleft);
 	    pcb->end_status = sgets(pcb->s, pcb->data + cleft, nread, &nread);
 	    set_cb_end(pcb, pcb->data + cleft + nread);
@@ -1907,8 +1946,11 @@
 
     /* get the segment size; refill command buffer if necessary */
     enc_u_getw(seg_size, cbp);
-    if (cbp + seg_size > pcb->limit)
-        cbp = top_up_cbuf(pcb, cbp);
+    if (cbp + seg_size > pcb->limit) {
+        code = top_up_cbuf(pcb, &cbp);
+	if (code < 0)
+	    return code;
+    }
 
     if (pht_buff->pbuff == 0) {
         /* if not separate buffer, must be only one segment */
@@ -2116,7 +2158,9 @@
     int code;
 
     /* This is sloppy, but we don't have enough information to do better. */
-    pcb->ptr = top_up_cbuf(pcb, pcb->ptr);
+    code = top_up_cbuf(pcb, &pcb->ptr);
+    if (code < 0)
+	return code;
     s_init(&s, NULL);
     sread_string(&s, pcb->ptr, pcb->end - pcb->ptr);
     code = image_type->sget(pic, &s, pcs);
@@ -2135,7 +2179,7 @@
     bool alloc_data_on_heap = false;
     byte *param_buf;
     uint param_length;
-    int code = 0;
+    int code;
 
     cmd_get_value(param_length, cbp);
     if_debug1('L', " length=%d\n", param_length);
@@ -2146,7 +2190,9 @@
 
     /* Make sure entire serialized param list is in cbuf */
     /* + force void* alignment */
-    cbp = top_up_cbuf(pcb, cbp);
+    code = top_up_cbuf(pcb, &cbp);
+    if (code < 0)
+	return code;
     if (pcb->end - cbp >= param_length) {
 	param_buf = (byte *)cbp;
 	cbp += param_length;
@@ -2228,8 +2274,11 @@
     gx_device *                 tdev = *ptarget;
 
     /* fill the command buffer (see comment above) */
-	if (pcb->end - cbp < MAX_CLIST_COMPOSITOR_SIZE + sizeof(comp_id))
-		cbp = top_up_cbuf(pcb, cbp);
+    if (pcb->end - cbp < MAX_CLIST_COMPOSITOR_SIZE + sizeof(comp_id)) {
+	code = top_up_cbuf(pcb, &cbp);
+	if (code < 0)
+	    return code;
+    }
 
     /* find the appropriate compositor method vector */
     comp_id = *cbp++;

Modified: trunk/gs/src/gxclread.c
===================================================================
--- trunk/gs/src/gxclread.c	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxclread.c	2007-11-15 07:22:43 UTC (rev 8369)
@@ -65,6 +65,7 @@
     uint left;			/* amount of data left in this run */
     cmd_block b_this;
 #ifdef DEBUG
+    bool skip_first;
     cbuf_offset_map_elem *offset_map;
     int offset_map_length;
     int offset_map_max_length;
@@ -87,27 +88,40 @@
 
 #ifdef DEBUG
 static int
-s_band_read_init_offset_map(stream_state * st, gs_memory_t *memory)
+s_band_read_init_offset_map(gx_device_clist_reader *crdev, stream_state * st)
 {
     stream_band_read_state *const ss = (stream_band_read_state *) st;
     const clist_io_procs_t *io_procs = ss->page_info.io_procs;
 
-    ss->offset_map_length = 0;
-    ss->offset_map_max_length = cbuf_size + 1; /* fixme: Wanted a more accurate implementation. */
-    ss->offset_map = (cbuf_offset_map_elem *)gs_alloc_byte_array(memory, 
-		ss->offset_map_max_length, sizeof(*ss->offset_map), "s_band_read_init_offset_map");
-    if (ss->offset_map == NULL)
-	return_error(gs_error_VMerror);
-    ss->offset_map[0].buffered = 0;
+    if (gs_debug_c('L')) {
+	ss->offset_map_length = 0;
+	ss->offset_map_max_length = cbuf_size + 1; /* fixme: Wanted a more accurate implementation. */
+	ss->offset_map = (cbuf_offset_map_elem *)gs_alloc_byte_array(crdev->memory, 
+		    ss->offset_map_max_length, sizeof(*ss->offset_map), "s_band_read_init_offset_map");
+	if (ss->offset_map == NULL)
+	    return_error(gs_error_VMerror);
+	ss->offset_map[0].buffered = 0;
+	crdev->offset_map = ss->offset_map; /* Prevent collecting it as garbage. 
+					    Debugged with ppmraw -r300 014-09.ps . */
+    } else {
+	ss->offset_map_length = 0;
+	ss->offset_map_max_length = 0;
+	ss->offset_map = NULL;
+	crdev->offset_map = NULL;
+    }
+    ss->skip_first = true;
     return 0;
 }
 
 static void
-s_band_read_dnit_offset_map(stream_state * st, gs_memory_t *memory)
+s_band_read_dnit_offset_map(gx_device_clist_reader *crdev, stream_state * st)
 {
-    stream_band_read_state *const ss = (stream_band_read_state *) st;
+    if (gs_debug_c('L')) {
+	stream_band_read_state *const ss = (stream_band_read_state *) st;
 
-    gs_free_object(memory, ss->offset_map, "s_band_read_dnit_offset_map");
+	gs_free_object(crdev->memory, ss->offset_map, "s_band_read_dnit_offset_map");
+	crdev->offset_map = 0;
+    }
 }
 #endif
 
@@ -131,7 +145,8 @@
 	    if (count > left)
 		count = left;
 #	    ifdef DEBUG
-	    ss->offset_map[ss->offset_map_length - 1].buffered += count;
+		if (gs_debug_c('L'))
+		    ss->offset_map[ss->offset_map_length - 1].buffered += count;
 #	    endif
 	    io_procs->fread_chars(q + 1, count, cfile);
 	    if (io_procs->ferror_code(cfile) < 0) {
@@ -141,7 +156,7 @@
 	    q += count;
 	    left -= count;
 	    process_interrupts(st->memory);
-continue;
+	    continue;
 	}
 rb:
 	/*
@@ -162,16 +177,18 @@
 	    if (!(ss->band_last >= bmin && ss->band_first <= bmax))
 		goto rb;
 	    io_procs->fseek(cfile, pos, SEEK_SET, ss->page_cfname);
+	    left = (uint) (ss->b_this.pos - pos);
 #	    ifdef DEBUG
-	    if (ss->offset_map_length >= ss->offset_map_max_length) {
-		gs_note_error(gs_error_unregistered); /* Must not happen. */
-		return ERRC;
+	    if (left > 0  && gs_debug_c('L')) {
+		if (ss->offset_map_length >= ss->offset_map_max_length) {
+		    gs_note_error(gs_error_unregistered); /* Must not happen. */
+		    return ERRC;
+		}
+		ss->offset_map[ss->offset_map_length].file_offset = pos;
+		ss->offset_map[ss->offset_map_length].buffered = 0;
+		ss->offset_map_length++;
 	    }
-	    ss->offset_map[ss->offset_map_length].file_offset = ss->b_this.pos;
-	    ss->offset_map[ss->offset_map_length].buffered = 0;
-	    ss->offset_map_length++;
 #	    endif
-	    left = (uint) (ss->b_this.pos - pos);
 	    if_debug7('l', 
 		      "[l]reading for bands (%d,%d) at bfile %ld, cfile %ld, length %u color %d rop %d\n",
 		      bmin, bmax,
@@ -181,7 +198,7 @@
 	}
     }
     pw->ptr = q;
-   ss->left = left;
+    ss->left = left;
     return status;
 }
 
@@ -220,25 +237,40 @@
     return ss->offset_map[i].file_offset + (uint)(buffer_offset - offset0);
 }
 
-
-void
+int
 top_up_offset_map(stream_state * st, const byte *buf, const byte *ptr, const byte *end)
 {
+    /* NOTE: The clist data are buffered in the clist reader buffer and in the 
+       internal buffer of the clist stream. Since the 1st buffer is not accessible
+       from s_band_read_process, offset_map corresponds the union of the 2 buffers.
+     */
     stream_band_read_state *const ss = (stream_band_read_state *) st;
 
-    if (ptr == end)
-	ss->offset_map_length = 0;
+    if (!gs_debug_c('L')) {
+	return 0;
+    } else if (ss->skip_first) {
+	/* Work around the trick with initializing the buffer pointer with the buffer end. */
+	ss->skip_first = false;
+	return 0;
+    } else if (ptr == buf)
+	return 0;
     else {
 	uint buffer_offset = ptr - buf;
 	uint offset0, consumed;
 	int i = buffer_segment_index(ss, buffer_offset, &offset0);
 	
+	if (i < 0)
+	    return_error(gs_error_unregistered); /* Must not happen. */
 	consumed = buffer_offset - offset0;
 	ss->offset_map[i].buffered -= consumed;
 	ss->offset_map[i].file_offset += consumed;
-	memmove(ss->offset_map, ss->offset_map + i, 
+	if (i) {
+	    memmove(ss->offset_map, ss->offset_map + i, 
 		(ss->offset_map_length - i) * sizeof(*ss->offset_map));
+	    ss->offset_map_length -= i;
+	}
     }
+    return 0;
 }
 #endif /* DEBUG */
 
@@ -313,8 +345,9 @@
     
     int code = 0;
 
-   /* Initialize for rendering if we haven't done so yet. */
+    /* Initialize for rendering if we haven't done so yet. */
     if (crdev->ymin < 0) {
+	crdev->offset_map = NULL;
 	code = clist_end_page(&cldev->writer);
 	if (code < 0)
 	    return code;
@@ -335,7 +368,7 @@
     crdev->pages = 0;
     crdev->num_pages = 0;
     crdev->band_complexity_array = NULL;
-
+    crdev->offset_map = NULL;
     return gx_clist_reader_read_band_complexity(dev);
 }
 
@@ -513,6 +546,7 @@
 	/* an infinite loop. */
 	crdev->ymin = band_begin_line;
 	crdev->ymax = band_end_line;
+	crdev->offset_map = NULL;
 	if (code < 0)
 	    return code;
     }
@@ -647,7 +681,7 @@
 
 	s_band_read_init((stream_state *)&rs);
 #	ifdef DEBUG
-	s_band_read_init_offset_map((stream_state *)&rs, crdev->memory);
+	s_band_read_init_offset_map(crdev, (stream_state *)&rs);
 #	endif
 	  /* The stream doesn't need a memory, but we'll need to access s.memory->gs_lib_ctx. */
 	s_init(&s, mem);
@@ -663,7 +697,7 @@
 	code = clist_playback_band(action, crdev, &s, target, x0, y0, mem);
 	vd_release_dc;
 #	ifdef DEBUG
-	s_band_read_dnit_offset_map((stream_state *)&rs, crdev->memory);
+	s_band_read_dnit_offset_map(crdev, (stream_state *)&rs);
 #	endif
     }
 

Modified: trunk/gs/src/gxclutil.c
===================================================================
--- trunk/gs/src/gxclutil.c	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxclutil.c	2007-11-15 07:22:43 UTC (rev 8369)
@@ -246,6 +246,7 @@
 	    lprintf1("cmd_put_list_op error at 0x%lx\n", (ulong) pcl->tail);
 	}
 #endif
+	if_debug2('L', ", to id=%ld , offset=%ld", pcl->tail->id, pcl->tail->size);
 	pcl->tail->size += size;
     } else {
 	/* Skip to an appropriate alignment boundary. */

Modified: trunk/gs/src/gxp1fill.c
===================================================================
--- trunk/gs/src/gxp1fill.c	2007-11-14 23:03:22 UTC (rev 8368)
+++ trunk/gs/src/gxp1fill.c	2007-11-15 07:22:43 UTC (rev 8369)
@@ -249,6 +249,7 @@
     gx_device *dev = ptfs->orig_dev;
     int code;
 
+    crdev->offset_map = NULL;
     crdev->page_info.io_procs->rewind(crdev->page_info.bfile, false, NULL);
     crdev->page_info.io_procs->rewind(crdev->page_info.cfile, false, NULL);
     code = clist_playback_file_bands(playback_action_render,



More information about the gs-cvs mailing list