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