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

leonardo at ghostscript.com leonardo at ghostscript.com
Thu May 22 11:06:24 PDT 2008


Author: leonardo
Date: 2008-05-22 11:06:22 -0700 (Thu, 22 May 2008)
New Revision: 8770

Modified:
   trunk/gs/src/gsptype1.c
   trunk/gs/src/gxcldev.h
   trunk/gs/src/gxclpath.c
   trunk/gs/src/gxclrast.c
   trunk/gs/src/gxclutil.c
Log:
Enhancement (graphics) : Delay applying type 1 raster patterns until clist interpretation (continued 4).

DETAILS :

The old code assumes that a pattern always fits into the clist writer buffer.
However ppmraw -r400 176-01.ps violates this assumption.
This patch implements a subdivision of a pattern into slices,
each of which is smaller than the buffer size.

1. The new function cmd_get_buffer_space retrives maximal available space
   in the clist writer buffer (gxclutil.c).

2. cmd_put_drawing_color now implements a cycle for slicing big patterns.
   Each slice writes to clist as a separate clist instruction (gxclpath.c).

3. gx_dc_pattern_write_raster drops the constraint that the pattern
   fits into a single buffer (gsptype1.c).

4. The clist interpreter is enhanced with composing a pattern from slices
   (gxclrast.c).

EXPECTED DIFFERENCES :

None.


Modified: trunk/gs/src/gsptype1.c
===================================================================
--- trunk/gs/src/gsptype1.c	2008-05-22 09:52:18 UTC (rev 8769)
+++ trunk/gs/src/gsptype1.c	2008-05-22 18:06:22 UTC (rev 8770)
@@ -1269,6 +1269,7 @@
     }
     if (offset1 == 0) {	/* Serialize tile parameters: */
 	gx_dc_serialized_tile_t buf;
+	gx_strip_bitmap buf1;
 
     	buf.id = ptile->id;
 	buf.size.x = 0; /* fixme: don't write with raster patterns. */
@@ -1289,20 +1290,28 @@
 	left -= sizeof(buf);
 	dp += sizeof(buf);
 	offset1 += sizeof(buf);
+
+	buf1 = ptile->tbits;
+	buf1.data = NULL; /* fixme: we don't need to write it actually. */
+	if (sizeof(buf1) > left) {
+	    /* For a while we require the client to provide enough buffer size. */
+	    return_error(gs_error_unregistered); /* Must not happen. */
+	}
+	memcpy(dp, &buf1, sizeof(buf1));
+	left -= sizeof(buf1);
+	dp += sizeof(buf1);
+	offset1 += sizeof(buf1);
     }
-    if (left < size_b)
-	return_error(gs_error_unregistered); /* Not implemented yet because cmd_put_drawing_color provides a big buffer. */
     if (offset1 <= sizeof(gx_dc_serialized_tile_t) + size_b) {
-	gx_strip_bitmap buf;
+	int l = min((size_b - sizeof(gx_strip_bitmap)) - (offset1 - sizeof(gx_dc_serialized_tile_t) -  sizeof(gx_strip_bitmap)), left);
 
-	buf = ptile->tbits;
-	buf.data = NULL; /* fixme: we don't need to write it actually. */
-	memcpy(dp, &buf, sizeof(buf));
-	memcpy(dp + sizeof(buf), ptile->tbits.data, size_b - sizeof(buf));
-	left -= size_b;
-	dp += size_b;
-	offset1 += size_b;
+	memcpy(dp, ptile->tbits.data + (offset1 - sizeof(gx_dc_serialized_tile_t) -  sizeof(gx_strip_bitmap)), l);
+	left -= l;
+	dp += l;
+	offset1 += l;
     }
+    if (left == 0)
+	return 0;
     if (size_c == 0)
 	return 0;
     if (offset1 <= sizeof(gx_dc_serialized_tile_t) + size_b + sizeof(gx_strip_bitmap)) {
@@ -1325,7 +1334,7 @@
     return 0;
 }
 
-/* currently, patterns cannot be passed through the command list */
+/* Write a pattern into command list, possibly dividing intoi portions. */
 int
 gx_dc_pattern_write(
     const gx_device_color *         pdevc,

Modified: trunk/gs/src/gxcldev.h
===================================================================
--- trunk/gs/src/gxcldev.h	2008-05-22 09:52:18 UTC (rev 8769)
+++ trunk/gs/src/gxcldev.h	2008-05-22 18:06:22 UTC (rev 8770)
@@ -378,6 +378,11 @@
 /* and allocate space for its data. */
 byte *cmd_put_list_op(gx_device_clist_writer * cldev, cmd_list * pcl, uint size);
 
+/* Request a space in the buffer. 
+   Writes out the buffer if necessary.
+   Returns the size of available space. */
+int cmd_get_buffer_space(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size);
+
 #ifdef DEBUG
 byte *cmd_put_op(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size);
 #else

Modified: trunk/gs/src/gxclpath.c
===================================================================
--- trunk/gs/src/gxclpath.c	2008-05-22 09:52:18 UTC (rev 8769)
+++ trunk/gs/src/gxclpath.c	2008-05-22 18:06:22 UTC (rev 8770)
@@ -105,6 +105,11 @@
     byte *                     dp;
     byte *                     dp0;
     gs_int_point               color_phase;
+    int			       buffer_space;
+    int			       offset = 0;
+    int			       left;
+    uint		       portion_size, prefix_size;
+    int			       req_size_final;
 
     /* see if the halftone must be inserted in the command list */
     if ( pdht != NULL                          &&
@@ -136,7 +141,7 @@
         return 0;
     else if (code < 0 && code != gs_error_rangecheck)
         return code;
-    req_size = dc_size + 2 + 1 + enc_u_sizew(dc_size);
+    left = dc_size;
 
     /* see if phase informaiton must be inserted in the command list */
     if ( pdcolor->type->get_phase(pdcolor, &color_phase) &&
@@ -148,27 +153,39 @@
                                      color_phase.y )) < 0  )
         return code;
 
-    /*
-     * Encoded device colors are small in comparison to the command
-     * buffer size (< 64 bytes), so we can just clear space in the
-     * command buffer for them.
-     */
-    if ((code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_extend, req_size)) < 0)
-        return code;
-    dp0 = dp;
-    dp[1] = cmd_opv_ext_put_drawing_color;
-    dp += 2;
-    *dp++ = di;
-    enc_u_putw(dc_size, dp);
-    code = pdcolor->type->write( pdcolor,
-                                 &pcls->sdc,
-                                 (gx_device *)cldev,
-				 0,
-                                 dp,
-                                 &dc_size );
-    if (code < 0) {
-        cldev->cnext = dp0;
-        return code;
+    while (left) {
+	prefix_size = 2 + 1 + (offset > 0 ? enc_u_sizew(offset) : 0);
+	req_size = left + prefix_size + enc_u_sizew(left);
+	code = cmd_get_buffer_space(cldev, pcls, req_size);
+	if (code < 0)
+	    return code;
+	buffer_space = min(code, req_size);
+	portion_size = buffer_space - prefix_size - enc_u_sizew(left);
+	req_size_final = portion_size + prefix_size + enc_u_sizew(portion_size);
+	if (req_size_final > buffer_space)
+	    return_error(gs_error_unregistered); /* Must not happen. */
+	if ((code = set_cmd_put_op(dp, cldev, pcls, cmd_opv_extend, req_size_final)) < 0)
+	    return code;
+	dp0 = dp;
+	dp[1] = cmd_opv_ext_put_drawing_color;
+	dp += 2;
+	*dp++ = di | (offset > 0 ? 0x80 : 0);
+	if (offset > 0)
+	    enc_u_putw(offset, dp);
+	enc_u_putw(portion_size, dp);
+	code = pdcolor->type->write( pdcolor,
+				     &pcls->sdc,
+				     (gx_device *)cldev,
+				     offset,
+				     dp,
+				     &portion_size);
+	if (code < 0) {
+	    if (offset == 0)
+		cldev->cnext = dp0;
+	    return code;
+	}
+	offset += portion_size;
+	left -= portion_size;
     }
 
     /* should properly calculate colors_used, but for now just punt */

Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c	2008-05-22 09:52:18 UTC (rev 8769)
+++ trunk/gs/src/gxclrast.c	2008-05-22 18:06:22 UTC (rev 8770)
@@ -1616,15 +1616,19 @@
 				    uint    color_size;
 				    int left, offset, l;
 				    const gx_device_color_type_t *  pdct;
+				    byte type_and_flag = *cbp++;
+				    byte is_continuation = type_and_flag & 0x80;				    
 
-				    pdct = gx_get_dc_type_from_index(*cbp++);
+				    pdct = gx_get_dc_type_from_index(type_and_flag & 0x7F);
 				    if (pdct == 0) {
 					code = gs_note_error(gs_error_rangecheck);
 					goto out;
 				    }
+				    offset = 0;
+				    if (is_continuation)
+					enc_u_getw(offset, cbp);
 				    enc_u_getw(color_size, cbp);
 				    left = color_size;
-				    offset = 0;
 				    if (!left) {
 					/* We still need to call pdct->read because it may change dev_color.type -
 					   see gx_dc_null_read.*/

Modified: trunk/gs/src/gxclutil.c
===================================================================
--- trunk/gs/src/gxclutil.c	2008-05-22 09:52:18 UTC (rev 8769)
+++ trunk/gs/src/gxclutil.c	2008-05-22 18:06:22 UTC (rev 8770)
@@ -279,6 +279,25 @@
     cldev->cnext = dp + size;
     return dp;
 }
+
+/* Request a space in the buffer. 
+   Writes out the buffer if necessary.
+   Returns the size of available space. */
+int
+cmd_get_buffer_space(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size)
+{
+    cmd_list * pcl = &pcls->list;
+
+    if (size + cmd_headroom > cldev->cend - cldev->cnext) {
+	cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run);
+	if (cldev->error_code < 0) {
+	    cldev->error_is_retryable = 0;	/* hard error */
+	    return cldev->error_code;
+	}
+    }
+    return cldev->cend - cldev->cnext - cmd_headroom;
+}
+
 #ifdef DEBUG
 byte *
 cmd_put_op(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size)



More information about the gs-cvs mailing list