outputFile support in bbox device

Alex Cherepanov <[email protected]>
Newsgroups gmane.comp.printing.ghostscript.patches
Organization Coscript Software
Message-ID <[email protected]>
Add OutputFile support to bbox device.

The new feature will be used to re-implement ps2epsi
bbox device as following:
(1) calculate bbox
(2) render epsi preview (or tiff preview) using normal
     GS devices.

Current bbox device is broken because the fix for
the bug 686892 "bbox device returns empty box" is still
not committed.
bbox.diff (text/plain, 10.3 KB)
Index: gs/src/gdevbbox.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevbbox.c,v
retrieving revision 1.12
diff -b -u -r1.12 gdevbbox.c
--- gs/src/gdevbbox.c	21 Apr 2003 15:39:46 -0000	1.12
+++ gs/src/gdevbbox.c	10 Aug 2003 13:49:41 -0000
@@ -19,6 +19,7 @@
 #include "math_.h"
 #include "memory_.h"
 #include "gx.h"
+#include "gp.h"                 /* for gp_file_name_sizeof */
 #include "gserrors.h"
 #include "gsparam.h"
 #include "gxdevice.h"
@@ -236,9 +237,16 @@
 private int
 bbox_close_device(gx_device * dev)
 {
+    int code;
     gx_device_bbox *const bdev = (gx_device_bbox *) dev;
     gx_device *tdev = bdev->target;
 
+    if (bdev->file) {
+        code = gx_device_close_output_file(dev, bdev->fname, bdev->file);
+        if(code < 0)
+            return code;
+    }
+    
     if (bdev->box_procs.init_box != box_procs_default.init_box) {
 	/*
 	 * This device was created as a wrapper for a compositor.
@@ -332,6 +340,7 @@
 private int
 bbox_open_device(gx_device * dev)
 {
+    int code;
     gx_device_bbox *const bdev = (gx_device_bbox *) dev;
 
     if (bdev->free_standing) {
@@ -341,12 +350,12 @@
     }
     if (bdev->box_procs.init_box == box_procs_default.init_box)
 	BBOX_INIT_BOX(bdev);
+    
     /* gx_forward_open_device doesn't exist */
     {
 	gx_device *tdev = bdev->target;
-	int code =
-	    (tdev && bdev->forward_open_close ? gs_opendevice(tdev) : 0);
 
+	code = (tdev && bdev->forward_open_close ? gs_opendevice(tdev) : 0);
 	bbox_copy_params(bdev, true);
 	return code;
     }
@@ -361,14 +370,40 @@
 	/*
 	 * This is a free-standing device.  Print the page bounding box.
 	 */
+	int code;
 	gs_rect bbox;
 
 	gx_device_bbox_bbox(bdev, &bbox);
-	dlprintf4("%%%%BoundingBox: %d %d %d %d\n",
+        if ( bdev->file && (bdev->has_format || bdev->new_fname)) {
+            code = gx_device_close_output_file(dev, bdev->fname, bdev->file);
+            if(code < 0)
+                return code;
+            bdev->file = 0;
+        }
+        bdev->new_fname = false;
+        
+        if (bdev->fname[0] && bdev->file == 0) {
+            code = gx_device_open_output_file(dev, bdev->fname,
+	        false, false, &bdev->file);
+            if (code < 0)
+                return code;
+        }
+        
+        if (bdev->file) {
+            code = fprintf(bdev->file, "%%%%BoundingBox: %d %d %d %d\n"
+	                               "%%%%HiResBoundingBox: %f %f %f %f\n",
 		  (int)floor(bbox.p.x), (int)floor(bbox.p.y),
-		  (int)ceil(bbox.q.x), (int)ceil(bbox.q.y));
-	dlprintf4("%%%%HiResBoundingBox: %f %f %f %f\n",
+		                   (int)ceil(bbox.q.x), (int)ceil(bbox.q.y),
 		  bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
+        } else {
+            code = dlprintf8("%%%%BoundingBox: %d %d %d %d\n"
+	                     "%%%%HiResBoundingBox: %f %f %f %f\n",
+		                   (int)floor(bbox.p.x), (int)floor(bbox.p.y),
+		                   (int)ceil(bbox.q.x), (int)ceil(bbox.q.y),
+		                   bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
+        }
+        if (code < 0)
+            return_error(gs_error_ioerror);
     }
     return gx_forward_output_page(dev, num_copies, flush);
 }
@@ -495,6 +530,9 @@
 
 /* ---------------- Parameters ---------------- */
 
+private const char * const iamPageBoundingBox = "PageBoundingBox";
+private const char * const iamOutputFile = "OutputFile";
+
 /* We implement get_params to provide a way to read out the bounding box. */
 private int
 bbox_get_params(gx_device * dev, gs_param_list * plist)
@@ -520,7 +558,20 @@
     bbox[2] = fixed2float(fbox.q.x);
     bbox[3] = fixed2float(fbox.q.y);
     bba.data = bbox, bba.size = 4, bba.persistent = false;
-    return param_write_float_array(plist, "PageBoundingBox", &bba);
+    code = param_write_float_array(plist, iamPageBoundingBox, &bba);
+    if (code < 0)
+	return code;
+ 
+    if(bdev->fname[0]) {
+        gs_param_string ofns;
+        ofns.data = (const byte *)bdev->fname;
+        ofns.size = strlen(bdev->fname);
+        ofns.persistent = false;
+        code = param_write_string(plist, iamOutputFile, &ofns);
+    } else {
+	code = param_write_null(plist, iamOutputFile);
+    }
+    return code;    
 }
 
 /* We implement put_params to ensure that we keep the important */
@@ -530,37 +581,80 @@
 bbox_put_params(gx_device * dev, gs_param_list * plist)
 {
     gx_device_bbox *const bdev = (gx_device_bbox *) dev;
-    int code;
-    int ecode = 0;
-    gs_param_name param_name;
+    int ecode=0, code;
     gs_param_float_array bba;
+    gs_param_string ofs;
+    enum tag_fname_status {
+        k_not_set=0, k_null=1, k_name=2, k_format=3
+    } fname_status = k_not_set;
 
-    code = param_read_float_array(plist, (param_name = "PageBoundingBox"),
-				  &bba);
+    code = param_read_float_array(plist, iamPageBoundingBox, &bba);
     switch (code) {
 	case 0:
-	    if (bba.size != 4) {
-		ecode = gs_note_error(gs_error_rangecheck);
-		goto e;
-	    }
+	    if (bba.size == 4)
 	    break;
+	    code = gs_note_error(gs_error_rangecheck);
 	default:
+	    param_signal_error(plist, iamPageBoundingBox, code);
 	    ecode = code;
-	  e:param_signal_error(plist, param_name, ecode);
 	case 1:
 	    bba.data = 0;
     }
 
+    code = param_read_string(plist, iamOutputFile, &ofs);
+    switch (code) {
+	case 0:
+	    if (bdev->LockSafetyParams &&
+		    bytes_compare(ofs.data, ofs.size,
+			(const byte *)bdev->fname, strlen(bdev->fname))) {
+	        code = gs_note_error(gs_error_invalidaccess);
+	    } else if (ofs.size >= gp_file_name_sizeof) {
+		code = gs_note_error(gs_error_limitcheck);
+	    } else {
+                gs_parsed_file_name_t parsed;
+                const char *fmt;
+                code = gx_parse_output_file_name(&parsed, &fmt, (const char *)ofs.data, ofs.size);
+                if (code >= 0)
+                    { fname_status = fmt ? k_format : k_name;
+                      break;
+                    }
+            }
+	default:
+	    if (param_read_null(plist, iamOutputFile) == 0) {
+  	        fname_status = k_null;
+                break;
+            }
+            param_signal_error(plist, iamOutputFile, code);
+	    ecode = code;
+	case 1:
+	    break;
+    }
+
     code = gx_forward_put_params(dev, plist);
-    if (ecode < 0)
-	code = ecode;
-    if (code >= 0 && bba.data != 0) {
+    if (code < 0)
+	ecode = code;
+
+    if (ecode >= 0) {
+        if( bba.data != 0) {
 	BBOX_INIT_BOX(bdev);
 	BBOX_ADD_RECT(bdev, float2fixed(bba.data[0]), float2fixed(bba.data[1]),
 		      float2fixed(bba.data[2]), float2fixed(bba.data[3]));
     }
+        
+        if (fname_status) { 
+            bdev->has_format = fname_status == k_format;
+            if (fname_status >= k_name) {
+                bdev->new_fname |= bdev->fname[ofs.size] || memcmp(bdev->fname, ofs.data, ofs.size);
+                memcpy(bdev->fname, ofs.data, ofs.size);
+                bdev->fname[ofs.size] = 0;
+            } else {
+                bdev->new_fname |= bdev->fname[0] != 0;
+                bdev->fname[0] = 0;
+            }
+        }
+    }
     bbox_copy_params(bdev, true);
-    return code;
+    return ecode;
 }
 
 /* ---------------- Polygon drawing ---------------- */
Index: gs/src/gdevbbox.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevbbox.h,v
retrieving revision 1.5
diff -b -u -r1.5 gdevbbox.h
--- gs/src/gdevbbox.h	16 Jun 2002 07:25:26 -0000	1.5
+++ gs/src/gdevbbox.h	10 Aug 2003 13:49:41 -0000
@@ -108,12 +108,17 @@
 	/* The following are updated dynamically. */\
 	gs_fixed_rect bbox;\
 	gx_color_index black, white;\
-	gx_color_index transparent /* white or gx_no_color_index */
+	gx_color_index transparent; /* white or gx_no_color_index */\
+        char fname[gp_file_name_sizeof];\
+        FILE *file;\
+        bool has_format;\
+        bool new_fname
 typedef struct gx_device_bbox_s gx_device_bbox;
 #define gx_device_bbox_common_initial(fs, foc, wio)\
   0 /* target */,\
   fs, foc, {0}, 0, wio,\
-  {{0, 0}, {0, 0}}, gx_no_color_index, gx_no_color_index, gx_no_color_index
+  {{0, 0}, {0, 0}}, gx_no_color_index, gx_no_color_index, gx_no_color_index,\
+  "", 0, false, false
 struct gx_device_bbox_s {
     gx_device_bbox_common;
 };
Index: gs/src/gximag3x.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gximag3x.c,v
retrieving revision 1.14
diff -b -u -r1.14 gximag3x.c
--- gs/src/gximag3x.c	28 Mar 2003 20:15:36 -0000	1.14
+++ gs/src/gximag3x.c	10 Aug 2003 13:49:41 -0000
@@ -20,6 +20,7 @@
 #include "math_.h"		/* for ceil, floor */
 #include "memory_.h"
 #include "gx.h"
+#include "gp.h"                 /* for gp_file_name_sizeof */
 #include "gserrors.h"
 #include "gsbitops.h"
 #include "gscspace.h"
Index: gs/src/lib.mak
===================================================================
RCS file: /cvs/ghostscript/gs/src/lib.mak,v
retrieving revision 1.130
diff -b -u -r1.130 lib.mak
--- gs/src/lib.mak	1 Aug 2003 15:53:37 -0000	1.130
+++ gs/src/lib.mak	10 Aug 2003 13:49:43 -0000
@@ -949,6 +949,7 @@
 	$(SETDEV2) $(GLD)bbox $(GLOBJ)gdevbbox.$(OBJ)
 
 $(GLOBJ)gdevbbox.$(OBJ) : $(GLSRC)gdevbbox.c $(GXERR) $(math__h) $(memory__h)\
+ $(gp_h)\
  $(gdevbbox_h) $(gsdevice_h) $(gsparam_h)\
  $(gxcpath_h) $(gxdcolor_h) $(gxdevice_h) $(gxiparam_h) $(gxistate_h)\
  $(gxpaint_h) $(gxpath_h)
@@ -2354,7 +2355,7 @@
 	$(GLCC) $(GLO_)gstrans.$(OBJ) $(C_) $(GLSRC)gstrans.c
 
 $(GLOBJ)gximag3x.$(OBJ) : $(GLSRC)gximag3x.c $(GXERR) $(math__h) $(memory__h)\
- $(gdevbbox_h)\
+ $(gdevbbox_h) $(gp_h)\
  $(gsbitops_h) $(gscpixel_h) $(gscspace_h) $(gsstruct_h)\
  $(gxdevice_h) $(gxdevmem_h) $(gximag3x_h) $(gxistate_h)
 	$(GLCC) $(GLO_)gximag3x.$(OBJ) $(C_) $(GLSRC)gximag3x.c
Index: gs/doc/Devices.htm
===================================================================
RCS file: /cvs/ghostscript/gs/doc/Devices.htm,v
retrieving revision 1.67
diff -b -u -r1.67 Devices.htm
--- gs/doc/Devices.htm	9 Jun 2003 21:55:07 -0000	1.67
+++ gs/doc/Devices.htm	10 Aug 2003 13:49:43 -0000
@@ -1138,8 +1138,9 @@
 <p></p>
 
 <p>
-Currently, it always prints the bounding box on <b><tt>stderr</tt></b>;
-eventually, it should also recognize <b><tt>-sOutputFile=</tt></b>.
+Old versions always print the bounding box on <b><tt>stderr</tt></b>.
+Since v. 8.11 <b><tt>-sOutputFile=</tt></b> is supported with
+default <b><tt>null</tt></b> value corresponding to <b><tt>stderr</tt></b>.
 
 <p>
 Note that this device, like other devices, has a resolution and a (maximum)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.