Coverage Report

Created: 2025-06-24 07:01

/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
}