xref: /plan9/sys/src/cmd/gs/src/gdevp2up.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevp2up.c,v 1.6 2004/05/26 04:10:58 dan Exp $ */
18 /* A "2-up" PCX device for testing page objects. */
19 #include "gdevprn.h"
20 #include "gdevpccm.h"
21 #include "gxclpage.h"
22 
23 extern gx_device_printer gs_pcx256_device;
24 
25 /* ------ The device descriptors ------ */
26 
27 /*
28  * Default X and Y resolution.
29  */
30 #define X_DPI 72
31 #define Y_DPI 72
32 
33 /*
34  * Define the size of the rendering buffer.
35  */
36 #define RENDER_BUFFER_SPACE 500000
37 
38 /* This device only supports SVGA 8-bit color. */
39 
40 private dev_proc_open_device(pcx2up_open);
41 private dev_proc_print_page(pcx2up_print_page);
42 
43 typedef struct gx_device_2up_s {
44     gx_device_common;
45     gx_prn_device_common;
46     bool have_odd_page;
47     gx_saved_page odd_page;
48 } gx_device_2up;
49 
50 private const gx_device_procs pcx2up_procs =
51 prn_color_procs(pcx2up_open, gdev_prn_output_page, gdev_prn_close,
52 		pc_8bit_map_rgb_color, pc_8bit_map_color_rgb);
53 gx_device_2up gs_pcx2up_device =
54 {prn_device_body(gx_device_2up, pcx2up_procs, "pcx2up",
55 		 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
56 		 X_DPI, Y_DPI,
57 		 0, 0, 0, 0,	/* margins */
58 		 3, 8, 5, 5, 6, 6, pcx2up_print_page)
59 };
60 
61 /* Open the device.  We reimplement this to force banding with */
62 /* delayed rasterizing. */
63 private int
pcx2up_open(gx_device * dev)64 pcx2up_open(gx_device * dev)
65 {
66     gx_device_printer *pdev = (gx_device_printer *) dev;
67     int code;
68     gdev_prn_space_params save_params;
69 
70     save_params = pdev->space_params;
71     pdev->space_params.MaxBitmap = 0;	/* force banding */
72     pdev->space_params.band.BandWidth =
73 	dev->width * 2 + (int)(dev->HWResolution[0] * 2.0);
74     pdev->space_params.band.BandBufferSpace = RENDER_BUFFER_SPACE;
75     code = gdev_prn_open(dev);
76     pdev->space_params = save_params;
77     ((gx_device_2up *) dev)->have_odd_page = false;
78     return code;
79 }
80 
81 /* Write the page. */
82 private int
pcx2up_print_page(gx_device_printer * pdev,FILE * file)83 pcx2up_print_page(gx_device_printer * pdev, FILE * file)
84 {
85     gx_device_2up *pdev2 = (gx_device_2up *) pdev;
86     const gx_device_printer *prdev_template =
87     (const gx_device_printer *)&gs_pcx2up_device;
88 
89     if (!pdev2->have_odd_page) {	/* This is the odd page, just save it. */
90 	pdev2->have_odd_page = true;
91 	return gdev_prn_save_page(pdev, &pdev2->odd_page, 1);
92     } else {			/* This is the even page, do 2-up output. */
93 	gx_saved_page even_page;
94 	gx_placed_page pages[2];
95 	int x_offset = (int)(pdev->HWResolution[0] * 0.5);
96 	int y_offset = (int)(pdev->HWResolution[1] * 0.5);
97 	int code = gdev_prn_save_page(pdev, &even_page, 1);
98 	int prdev_size = prdev_template->params_size;
99 	gx_device_printer *prdev;
100 
101 #define rdev ((gx_device *)prdev)
102 
103 	if (code < 0)
104 	    return code;
105 	/* Create the placed page list. */
106 	pages[0].page = &pdev2->odd_page;
107 	pages[0].offset.x = x_offset;
108 	pages[0].offset.y = 0 /*y_offset */ ;
109 	pages[1].page = &even_page;
110 	pages[1].offset.x = pdev->width + x_offset * 3;
111 	pages[1].offset.y = 0 /*y_offset */ ;
112 	/* Create and open a device for rendering. */
113 	prdev = (gx_device_printer *)
114 	    gs_alloc_bytes(pdev->memory, prdev_size,
115 			   "pcx2up_print_page(device)");
116 	if (prdev == 0)
117 	    return_error(gs_error_VMerror);
118 	memcpy(prdev, prdev_template, prdev_size);
119         check_device_separable((gx_device *)rdev);
120 	gx_device_fill_in_procs(rdev);
121 	set_dev_proc(prdev, open_device,
122 		     dev_proc(&gs_pcx256_device, open_device));
123 	prdev->printer_procs.print_page =
124 	    gs_pcx256_device.printer_procs.print_page;
125 	prdev->space_params.band =
126 	    pages[0].page->info.band_params;	/* either one will do */
127 	prdev->space_params.MaxBitmap = 0;
128 	prdev->space_params.BufferSpace =
129 	    prdev->space_params.band.BandBufferSpace;
130 	prdev->width = prdev->space_params.band.BandWidth;
131 	prdev->OpenOutputFile = false;
132 	code = (*dev_proc(rdev, open_device)) (rdev);
133 	if (code < 0)
134 	    return code;
135 	rdev->is_open = true;
136 	prdev->file = pdev->file;
137 	/* Render the pages. */
138 	code = gdev_prn_render_pages(prdev, pages, 2);
139 	/* Clean up. */
140 	if (pdev->file != 0)
141 	    prdev->file = 0;	/* don't close it */
142 	gs_closedevice(rdev);
143 	pdev2->have_odd_page = false;
144 	return code;
145 #undef rdev
146     }
147 }
148