xref: /plan9/sys/src/cmd/gs/src/gdevppla.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 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: gdevppla.c,v 1.4 2002/02/21 22:24:51 giles Exp $ */
18 /* Support for printer devices with planar buffering. */
19 #include "gdevprn.h"
20 #include "gdevmpla.h"
21 #include "gdevppla.h"
22 
23 
24 /* Set the buf_procs in a printer device to planar mode. */
25 int
gdev_prn_set_procs_planar(gx_device * dev)26 gdev_prn_set_procs_planar(gx_device *dev)
27 {
28     gx_device_printer * const pdev = (gx_device_printer *)dev;
29 
30     pdev->printer_procs.buf_procs.create_buf_device =
31 	gdev_prn_create_buf_planar;
32     pdev->printer_procs.buf_procs.size_buf_device =
33 	gdev_prn_size_buf_planar;
34     return 0;
35 }
36 
37 /* Open a printer device, conditionally setting it to be planar. */
38 int
gdev_prn_open_planar(gx_device * dev,bool upb)39 gdev_prn_open_planar(gx_device *dev, bool upb)
40 {
41     if (upb)
42 	gdev_prn_set_procs_planar(dev);
43     return gdev_prn_open(dev);
44 }
45 
46 /* Augment get/put_params to add UsePlanarBuffer. */
47 int
gdev_prn_get_params_planar(gx_device * pdev,gs_param_list * plist,bool * pupb)48 gdev_prn_get_params_planar(gx_device * pdev, gs_param_list * plist,
49 			   bool *pupb)
50 {
51     int ecode = gdev_prn_get_params(pdev, plist);
52 
53     if (ecode < 0)
54 	return ecode;
55     return param_write_bool(plist, "UsePlanarBuffer", pupb);
56 }
57 int
gdev_prn_put_params_planar(gx_device * pdev,gs_param_list * plist,bool * pupb)58 gdev_prn_put_params_planar(gx_device * pdev, gs_param_list * plist,
59 			   bool *pupb)
60 {
61     bool upb = *pupb;
62     int ecode = 0, code;
63 
64     if (pdev->color_info.num_components > 1)
65 	ecode = param_read_bool(plist, "UsePlanarBuffer", &upb);
66     code = gdev_prn_put_params(pdev, plist);
67     if (ecode >= 0)
68 	ecode = code;
69     if (ecode >= 0)
70 	*pupb = upb;
71     return ecode;
72 }
73 
74 /* Set the buffer device to planar mode. */
75 private int
gdev_prn_set_planar(gx_device_memory * mdev,const gx_device * tdev)76 gdev_prn_set_planar(gx_device_memory *mdev, const gx_device *tdev)
77 {
78     int num_comp = tdev->color_info.num_components;
79     gx_render_plane_t planes[4];
80     int depth = tdev->color_info.depth / num_comp;
81 
82     if (num_comp < 3 || num_comp > 4)
83 	return_error(gs_error_rangecheck);
84     /* Round up the depth per plane to a power of 2. */
85     while (depth & (depth - 1))
86 	--depth, depth = (depth | (depth >> 1)) + 1;
87     planes[3].depth = planes[2].depth = planes[1].depth = planes[0].depth =
88 	depth;
89     /* We want the most significant plane to come out first. */
90     planes[0].shift = depth * (num_comp - 1);
91     planes[1].shift = planes[0].shift - depth;
92     planes[2].shift = planes[1].shift - depth;
93     planes[3].shift = 0;
94     return gdev_mem_set_planar(mdev, num_comp, planes);
95 }
96 
97 /* Create a planar buffer device. */
98 int
gdev_prn_create_buf_planar(gx_device ** pbdev,gx_device * target,const gx_render_plane_t * render_plane,gs_memory_t * mem,bool for_band)99 gdev_prn_create_buf_planar(gx_device **pbdev, gx_device *target,
100 			   const gx_render_plane_t *render_plane,
101 			   gs_memory_t *mem, bool for_band)
102 {
103     int code = gx_default_create_buf_device(pbdev, target, render_plane, mem,
104 					    for_band);
105 
106     if (code < 0)
107 	return code;
108     if (gs_device_is_memory(*pbdev) /* == render_plane->index < 0 */) {
109 	code = gdev_prn_set_planar((gx_device_memory *)*pbdev, *pbdev);
110     }
111     return code;
112 }
113 
114 /* Determine the space needed by a planar buffer device. */
115 int
gdev_prn_size_buf_planar(gx_device_buf_space_t * space,gx_device * target,const gx_render_plane_t * render_plane,int height,bool for_band)116 gdev_prn_size_buf_planar(gx_device_buf_space_t *space, gx_device *target,
117 			 const gx_render_plane_t *render_plane,
118 			 int height, bool for_band)
119 {
120     gx_device_memory mdev;
121 
122     if (render_plane && render_plane->index >= 0)
123 	return gx_default_size_buf_device(space, target, render_plane,
124 					  height, for_band);
125     mdev.color_info = target->color_info;
126     gdev_prn_set_planar(&mdev, target);
127     space->bits = gdev_mem_bits_size(&mdev, target->width, height);
128     space->line_ptrs = gdev_mem_line_ptrs_size(&mdev, target->width, height);
129     space->raster = bitmap_raster(target->width * mdev.planes[0].depth);
130     return 0;
131 }
132