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)