Coverage Report

Created: 2025-06-10 07:26

/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
0
{
27
0
    gx_device_printer * const pdev = (gx_device_printer *)dev;
28
29
0
    pdev->printer_procs.buf_procs.create_buf_device =
30
0
        gdev_prn_create_buf_planar;
31
0
    pdev->printer_procs.buf_procs.size_buf_device =
32
0
        gdev_prn_size_buf_planar;
33
0
    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
0
    return 0;
36
0
}
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
0
{
42
0
    if (num_planar_planes) {
43
0
        gdev_prn_set_procs_planar(dev);
44
0
        dev->num_planar_planes = num_planar_planes;
45
0
    }
46
0
    return gdev_prn_open(dev);
47
0
}
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
0
{
64
0
    bool upb = *pupb;
65
0
    int ecode = 0, code;
66
67
0
    if (pdev->color_info.num_components > 1)
68
0
        ecode = param_read_bool(plist, "UsePlanarBuffer", &upb);
69
0
    code = gdev_prn_put_params(pdev, plist);
70
0
    if (ecode >= 0)
71
0
        ecode = code;
72
0
    if (ecode >= 0)
73
0
        *pupb = upb;
74
0
    return ecode;
75
0
}
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
0
{
81
0
    int num_comp = tdev->num_planar_planes;
82
0
    gx_render_plane_t planes[GX_DEVICE_COLOR_MAX_COMPONENTS];
83
0
    int depth = tdev->color_info.depth / num_comp;
84
0
    int k;
85
86
0
    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
0
    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
0
    planes[num_comp-1].shift = 0;
94
0
    planes[num_comp-1].depth = depth;
95
0
    for (k = (num_comp - 2); k >= 0; k--) {
96
0
        planes[k].depth = depth;
97
0
        planes[k].shift = planes[k + 1].shift + depth;
98
0
    }
99
0
    return gdev_mem_set_planar(mdev, num_comp, planes);
100
0
}
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
0
{
108
0
    int code = gx_default_create_buf_device(pbdev, target, y, render_plane, mem,
109
0
                                            for_band);
110
111
0
    if (code < 0)
112
0
        return code;
113
0
    if (gs_device_is_memory(*pbdev) /* == render_plane->index < 0 */) {
114
0
        code = gdev_prn_set_planar((gx_device_memory *)*pbdev, *pbdev);
115
0
    }
116
0
    return code;
117
0
}
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
0
{
125
0
    gx_device_memory mdev = { 0 };
126
0
    int code;
127
128
0
    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
0
    mdev.color_info = target->color_info;
132
0
    mdev.pad = target->pad;
133
0
    mdev.log2_align_mod = target->log2_align_mod;
134
0
    mdev.num_planar_planes = target->num_planar_planes;
135
0
    mdev.graphics_type_tag = target->graphics_type_tag;
136
0
    code = gdev_prn_set_planar(&mdev, target);
137
0
    if (code < 0)
138
0
        return code;
139
0
    if (gdev_mem_bits_size(&mdev, target->width, height, &(space->bits)) < 0)
140
0
        return_error(gs_error_VMerror);
141
0
    space->line_ptrs = gdev_mem_line_ptrs_size(&mdev, target->width, height);
142
0
    space->raster = bitmap_raster_pad_align(target->width * mdev.planes[0].depth, mdev.pad, mdev.log2_align_mod);
143
0
    return 0;
144
0
}