Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gximask.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 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
/* Functions for masked fill optimization. */
18
#include "gx.h"
19
#include "memory_.h"
20
#include "gserrors.h"
21
#include "gsptype1.h"
22
#include "gsptype2.h"
23
#include "gxdevice.h"
24
#include "gxdcolor.h"
25
#include "gxcpath.h"
26
#include "gximask.h"
27
#include "gzacpath.h"
28
#include "gzcpath.h"
29
#include "gxdevsop.h"
30
31
/* Functions for masked fill optimization. */
32
/* Imagemask with a shading color would paint entire shading for each rectangle of the mask.
33
   These functions convert the mask into a clipping path and then render entire shading
34
   at once through it.
35
*/
36
37
int
38
gx_image_fill_masked_start(gx_device *dev, const gx_device_color *pdevc, bool transpose,
39
                           const gx_clip_path *pcpath, gs_memory_t *mem, gs_logical_operation_t lop,
40
                           gx_device **cdev)
41
90.1M
{
42
90.1M
    if ((lop == lop_default) && (gx_dc_is_pattern2_color(pdevc) || gx_dc_is_pattern1_color_clist_based(pdevc))) {
43
5.21k
        if (!dev_proc(dev, dev_spec_op)(dev, gxdso_pattern_can_accum, NULL, gs_no_id)) {
44
5.19k
            extern_st(st_device_cpath_accum);
45
5.19k
            gx_device_cpath_accum *pcdev;
46
5.19k
            gs_fixed_rect cbox;
47
48
5.19k
            if (pcpath == NULL)
49
0
                return_error(gs_error_nocurrentpoint);  /* close enough if no clip path */
50
5.19k
            pcdev =  gs_alloc_struct(mem,
51
5.19k
                    gx_device_cpath_accum, &st_device_cpath_accum, "gx_image_fill_masked_start");
52
5.19k
            if (pcdev == NULL)
53
0
                return_error(gs_error_VMerror);
54
5.19k
            gx_cpath_accum_begin(pcdev, mem, transpose);
55
5.19k
            gx_cpath_outer_box(pcpath, &cbox);
56
5.19k
            gx_cpath_accum_set_cbox(pcdev, &cbox);
57
5.19k
            pcdev->rc.memory = mem;
58
5.19k
            pcdev->width = dev->width;   /* For gx_default_copy_mono. */
59
5.19k
            pcdev->height = dev->height; /* For gx_default_copy_mono. */
60
5.19k
            gx_device_retain((gx_device *)pcdev, true);
61
5.19k
            *cdev = (gx_device *)pcdev;
62
5.19k
        } else{
63
15
            *cdev = dev;
64
15
        }
65
5.21k
    } else
66
90.0M
        *cdev = dev;
67
90.1M
    return 0;
68
90.1M
}
69
70
int
71
gx_image_fill_masked_end(gx_device *dev, gx_device *tdev, const gx_device_color *pdevc)
72
5.14k
{
73
5.14k
    gx_device_cpath_accum *pcdev = (gx_device_cpath_accum *)dev;
74
5.14k
    gx_clip_path cpath;
75
5.14k
    gx_clip_path cpath_with_shading_bbox;
76
5.14k
    const gx_clip_path *pcpath1 = &cpath;
77
5.14k
    gx_device_clip cdev;
78
5.14k
    int code, code1;
79
80
5.14k
    gx_cpath_init_local(&cpath, pcdev->memory);
81
5.14k
    code = gx_cpath_accum_end(pcdev, &cpath);
82
5.14k
    if (code >= 0)
83
5.14k
        code = gx_dc_pattern2_clip_with_bbox(pdevc, tdev, &cpath_with_shading_bbox, &pcpath1);
84
5.14k
    gx_make_clip_device_on_stack(&cdev, pcpath1, tdev);
85
5.14k
    if (code >= 0 && pcdev->bbox.p.x < pcdev->bbox.q.x) {
86
4.14k
        code1 = gx_device_color_fill_rectangle(pdevc,
87
4.14k
                    pcdev->bbox.p.x, pcdev->bbox.p.y,
88
4.14k
                    pcdev->bbox.q.x - pcdev->bbox.p.x,
89
4.14k
                    pcdev->bbox.q.y - pcdev->bbox.p.y,
90
4.14k
                    (gx_device *)&cdev, lop_default, 0);
91
4.14k
        if (code == 0)
92
4.14k
            code = code1;
93
4.14k
    }
94
5.14k
    gx_destroy_clip_device_on_stack(&cdev);
95
5.14k
    if (pcpath1 == &cpath_with_shading_bbox)
96
0
        gx_cpath_free(&cpath_with_shading_bbox, "s_image_cleanup");
97
5.14k
    gx_device_retain((gx_device *)pcdev, false);
98
5.14k
    gx_cpath_free(&cpath, "s_image_cleanup");
99
5.14k
    return code;
100
5.14k
}
101
102
int
103
gx_image_fill_masked(gx_device *dev,
104
    const byte *data, int data_x, int raster, gx_bitmap_id id,
105
    int x, int y, int width, int height,
106
    const gx_device_color *pdc, int depth,
107
    gs_logical_operation_t lop, const gx_clip_path *pcpath)
108
89.1M
{
109
89.1M
    gx_device *cdev = dev;
110
89.1M
    int code;
111
112
89.1M
    if ((code = gx_image_fill_masked_start(dev, pdc, false, pcpath, dev->memory, lop, &cdev)) < 0)
113
0
        return code;
114
115
89.1M
    if (cdev == dev)
116
89.1M
        code = (*dev_proc(cdev, fill_mask))(cdev, data, data_x, raster, id,
117
89.1M
                            x, y, width, height, pdc, depth, lop, pcpath);
118
4.30k
    else {
119
        /* cdev != dev means that a cpath_accum device was inserted */
120
4.30k
        gx_device_color dc_temp;   /* if fill_masked_start did cpath_accum, use pure color */
121
122
4.30k
        set_nonclient_dev_color(&dc_temp, 1);    /* arbitrary color since cpath_accum doesn't use it */
123
4.30k
        if ((code = (*dev_proc(cdev, fill_mask))(cdev, data, data_x, raster, id,
124
4.30k
                            x, y, width, height, &dc_temp, depth, lop, pcpath)) < 0)
125
0
            return code;
126
4.30k
        code = gx_image_fill_masked_end(cdev, dev, pdc);    /* fill with the actual device color */
127
4.30k
    }
128
89.1M
    return code;
129
89.1M
}