/src/ghostpdl/base/gdevppla.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 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, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Support for printer devices with planar buffering. */ |
18 | | #include "gdevprn.h" |
19 | | #include "gdevmpla.h" |
20 | | #include "gdevppla.h" |
21 | | #include "gxdevsop.h" |
22 | | |
23 | | /* Set the buf_procs in a printer device to planar mode. */ |
24 | | int |
25 | | gdev_prn_set_procs_planar(gx_device *dev) |
26 | 36.6k | { |
27 | 36.6k | gx_device_printer * const pdev = (gx_device_printer *)dev; |
28 | | |
29 | 36.6k | pdev->printer_procs.buf_procs.create_buf_device = |
30 | 36.6k | gdev_prn_create_buf_planar; |
31 | 36.6k | pdev->printer_procs.buf_procs.size_buf_device = |
32 | 36.6k | gdev_prn_size_buf_planar; |
33 | 36.6k | if (dev_proc(pdev, dev_spec_op) == gx_default_dev_spec_op) |
34 | 0 | set_dev_proc(pdev, dev_spec_op, gdev_prn_dev_spec_op); |
35 | 36.6k | return 0; |
36 | 36.6k | } |
37 | | |
38 | | /* Open a printer device, conditionally setting it to be planar. */ |
39 | | int |
40 | | gdev_prn_open_planar(gx_device *dev, int num_planar_planes) |
41 | 52.6k | { |
42 | 52.6k | if (num_planar_planes) { |
43 | 36.6k | gdev_prn_set_procs_planar(dev); |
44 | 36.6k | dev->num_planar_planes = num_planar_planes; |
45 | 36.6k | } |
46 | 52.6k | return gdev_prn_open(dev); |
47 | 52.6k | } |
48 | | |
49 | | /* Augment get/put_params to add UsePlanarBuffer. */ |
50 | | int |
51 | | gdev_prn_get_params_planar(gx_device * pdev, gs_param_list * plist, |
52 | | bool *pupb) |
53 | 0 | { |
54 | 0 | int ecode = gdev_prn_get_params(pdev, plist); |
55 | |
|
56 | 0 | if (ecode < 0) |
57 | 0 | return ecode; |
58 | 0 | return param_write_bool(plist, "UsePlanarBuffer", pupb); |
59 | 0 | } |
60 | | int |
61 | | gdev_prn_put_params_planar(gx_device * pdev, gs_param_list * plist, |
62 | | bool *pupb) |
63 | 72.8k | { |
64 | 72.8k | bool upb = *pupb; |
65 | 72.8k | int ecode = 0, code; |
66 | | |
67 | 72.8k | if (pdev->color_info.num_components > 1) |
68 | 0 | ecode = param_read_bool(plist, "UsePlanarBuffer", &upb); |
69 | 72.8k | code = gdev_prn_put_params(pdev, plist); |
70 | 72.8k | if (ecode >= 0) |
71 | 72.8k | ecode = code; |
72 | 72.8k | if (ecode >= 0) |
73 | 72.8k | *pupb = upb; |
74 | 72.8k | return ecode; |
75 | 72.8k | } |
76 | | |
77 | | /* Set the buffer device to planar mode. */ |
78 | | static int |
79 | | gdev_prn_set_planar(gx_device_memory *mdev, const gx_device *tdev) |
80 | 7.70M | { |
81 | 7.70M | int num_comp = tdev->num_planar_planes; |
82 | 7.70M | gx_render_plane_t planes[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
83 | 7.70M | int depth = tdev->color_info.depth / num_comp; |
84 | 7.70M | int k; |
85 | | |
86 | 7.70M | if (num_comp < 1 || num_comp > GX_DEVICE_COLOR_MAX_COMPONENTS) |
87 | 0 | return_error(gs_error_rangecheck); |
88 | | /* Round up the depth per plane to a power of 2. */ |
89 | 7.70M | while (depth & (depth - 1)) |
90 | 0 | --depth, depth = (depth | (depth >> 1)) + 1; |
91 | | |
92 | | /* We want the most significant plane to come out first. */ |
93 | 7.70M | planes[num_comp-1].shift = 0; |
94 | 7.70M | planes[num_comp-1].depth = depth; |
95 | 40.5M | for (k = (num_comp - 2); k >= 0; k--) { |
96 | 32.8M | planes[k].depth = depth; |
97 | 32.8M | planes[k].shift = planes[k + 1].shift + depth; |
98 | 32.8M | } |
99 | 7.70M | return gdev_mem_set_planar(mdev, num_comp, planes); |
100 | 7.70M | } |
101 | | |
102 | | /* Create a planar buffer device. */ |
103 | | int |
104 | | gdev_prn_create_buf_planar(gx_device **pbdev, gx_device *target, int y, |
105 | | const gx_render_plane_t *render_plane, |
106 | | gs_memory_t *mem, gx_color_usage_t *for_band) |
107 | 7.65M | { |
108 | 7.65M | int code = gx_default_create_buf_device(pbdev, target, y, render_plane, mem, |
109 | 7.65M | for_band); |
110 | | |
111 | 7.65M | if (code < 0) |
112 | 0 | return code; |
113 | 7.65M | if (gs_device_is_memory(*pbdev) /* == render_plane->index < 0 */) { |
114 | 7.65M | code = gdev_prn_set_planar((gx_device_memory *)*pbdev, *pbdev); |
115 | 7.65M | } |
116 | 7.65M | return code; |
117 | 7.65M | } |
118 | | |
119 | | /* Determine the space needed by a planar buffer device. */ |
120 | | int |
121 | | gdev_prn_size_buf_planar(gx_device_buf_space_t *space, gx_device *target, |
122 | | const gx_render_plane_t *render_plane, |
123 | | int height, bool for_band) |
124 | 55.3k | { |
125 | 55.3k | gx_device_memory mdev = { 0 }; |
126 | 55.3k | int code; |
127 | | |
128 | 55.3k | if (render_plane && render_plane->index >= 0) |
129 | 0 | return gx_default_size_buf_device(space, target, render_plane, |
130 | 0 | height, for_band); |
131 | 55.3k | mdev.color_info = target->color_info; |
132 | 55.3k | mdev.pad = target->pad; |
133 | 55.3k | mdev.log2_align_mod = target->log2_align_mod; |
134 | 55.3k | mdev.num_planar_planes = target->num_planar_planes; |
135 | 55.3k | mdev.graphics_type_tag = target->graphics_type_tag; |
136 | 55.3k | code = gdev_prn_set_planar(&mdev, target); |
137 | 55.3k | if (code < 0) |
138 | 0 | return code; |
139 | 55.3k | if (gdev_mem_bits_size(&mdev, target->width, height, &(space->bits)) < 0) |
140 | 0 | return_error(gs_error_VMerror); |
141 | 55.3k | space->line_ptrs = gdev_mem_line_ptrs_size(&mdev, target->width, height); |
142 | 55.3k | space->raster = bitmap_raster_pad_align(target->width * mdev.planes[0].depth, mdev.pad, mdev.log2_align_mod); |
143 | 55.3k | return 0; |
144 | 55.3k | } |