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