1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 /* $Id: gdevbbox.h 8022 2007-06-05 22:23:38Z giles $ */
14 /* Definitions and interface for bbox (bounding box accumulator) device */
15 /* Requires gxdevice.h */
16 
17 #ifndef gdevbbox_INCLUDED
18 #  define gdevbbox_INCLUDED
19 
20 /*
21  * This device keeps track of the per-page bounding box, and also optionally
22  * forwards all drawing commands to a target.  It can be used either as a
23  * free-standing device or as a component (e.g., by the EPS writer).
24  *
25  * One way to use a bounding box device is simply to include bbox.dev in the
26  * value of DEVICE_DEVSn in the makefile.  This produces a free-standing
27  * device named 'bbox' that can be selected in the usual way (-sDEVICE=bbox)
28  * and that prints out the bounding box at each showpage or copypage without
29  * doing any drawing.
30  *
31  * The other way to use a bounding box device is from C code as a component
32  * in a device pipeline.  To set up a bounding box device that doesn't do
33  * any drawing:
34  *      gx_device_bbox *bdev =
35  *        gs_alloc_struct_immovable(some_memory,
36  *                                  gx_device_bbox, &st_device_bbox,
37  *                                  "some identifying string for debugging");
38  *      gx_device_bbox_init(bdev, NULL);
39  * Non-drawing bounding box devices have an "infinite" page size.
40  *
41  * To set up a bounding box device that draws to another device tdev:
42  *      gx_device_bbox *bdev =
43  *        gs_alloc_struct_immovable(some_memory,
44  *                                  gx_device_bbox, &st_device_bbox,
45  *                                  "some identifying string for debugging");
46  *      gx_device_bbox_init(bdev, tdev);
47  * Bounding box devices that draw to a real device appear to have the
48  * same page size as that device.
49  *
50  * To intercept the end-of-page to call a routine eop of your own, after
51  * setting up the device:
52  *      dev_proc_output_page(eop);      -- declare a prototype for eop
53  *      ...
54  *      set_dev_proc(bdev, output_page, eop);
55  *      ...
56  *      int eop(gx_device *dev, int num_copies, int flush)
57  *      {       gs_rect bbox;
58  *              gx_device_bbox_bbox((gx_device_bbox *)dev, &bbox);
59  *              << do whatever you want >>
60  *              return gx_forward_output_page(dev, num_copies, flush);
61  *      }
62  *
63  * Note that bounding box devices, unlike almost all other forwarding
64  * devices, conditionally propagate the open_device and close_device
65  * calls to their target.  By default, they do propagate these calls:
66  * use gx_device_bbox_fwd_open_close to change this if you want.
67  */
68 /*
69  * Define virtual procedures for managing the accumulated bounding box.
70  * These may be redefined by subclasses, and are also used for compositors.
71  */
72 typedef struct gx_device_bbox_procs_s {
73 
74 #define dev_bbox_proc_init_box(proc)\
75   bool proc(void *proc_data)
76     dev_bbox_proc_init_box((*init_box));
77 
78 #define dev_bbox_proc_get_box(proc)\
79   void proc(const void *proc_data, gs_fixed_rect *pbox)
80     dev_bbox_proc_get_box((*get_box));
81 
82 #define dev_bbox_proc_add_rect(proc)\
83   void proc(void *proc_data, fixed x0, fixed y0, fixed x1, fixed y1)
84     dev_bbox_proc_add_rect((*add_rect));
85 
86 #define dev_bbox_proc_in_rect(proc)\
87   bool proc(const void *proc_data, const gs_fixed_rect *pbox)
88     dev_bbox_proc_in_rect((*in_rect));
89 
90 } gx_device_bbox_procs_t;
91 /* Default implementations */
92 dev_bbox_proc_init_box(bbox_default_init_box);
93 dev_bbox_proc_get_box(bbox_default_get_box);
94 dev_bbox_proc_add_rect(bbox_default_add_rect);
95 dev_bbox_proc_in_rect(bbox_default_in_rect);
96 
97 #define gx_device_bbox_common\
98 	gx_device_forward_common;\
99 	bool free_standing;\
100 	bool forward_open_close;\
101 	gx_device_bbox_procs_t box_procs;\
102 	void *box_proc_data;\
103 	bool white_is_opaque;\
104 	/* The following are updated dynamically. */\
105 	gs_fixed_rect bbox;\
106 	gx_color_index black, white;\
107 	gx_color_index transparent /* white or gx_no_color_index */
108 typedef struct gx_device_bbox_s gx_device_bbox;
109 #define gx_device_bbox_common_initial(fs, foc, wio)\
110   0 /* target */,\
111   fs, foc, {0}, 0, wio,\
112   {{0, 0}, {0, 0}}, gx_no_color_index, gx_no_color_index, gx_no_color_index
113 struct gx_device_bbox_s {
114     gx_device_bbox_common;
115 };
116 
117 extern_st(st_device_bbox);
118 #define public_st_device_bbox()	/* in gdevbbox.c */\
119   gs_public_st_suffix_add1_final(st_device_bbox, gx_device_bbox,\
120     "gx_device_bbox", device_bbox_enum_ptrs, device_bbox_reloc_ptrs,\
121     gx_device_finalize, st_device_forward, box_proc_data)
122 
123 /* Initialize a bounding box device. */
124 void gx_device_bbox_init(gx_device_bbox * dev, gx_device * target, gs_memory_t *mem);
125 
126 /* Set whether a bounding box device propagates open/close to its target. */
127 void gx_device_bbox_fwd_open_close(gx_device_bbox * dev,
128 				   bool forward_open_close);
129 
130 /* Set whether a bounding box device considers white to be opaque. */
131 void gx_device_bbox_set_white_opaque(gx_device_bbox *dev,
132 				     bool white_is_opaque);
133 
134 /* Read back the bounding box in 1/72" units. */
135 void gx_device_bbox_bbox(gx_device_bbox * dev, gs_rect * pbbox);
136 
137 /* Release a bounding box device. */
138 void gx_device_bbox_release(gx_device_bbox *dev);
139 
140 #endif /* gdevbbox_INCLUDED */
141