Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/spwgd.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2017-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* PWGDecode filter */
18
#include "stdio_.h"   /* includes std.h */
19
#include "memory_.h"
20
#include "strimpl.h"
21
#include "spwgx.h"
22
23
/* ------ RunLengthDecode ------ */
24
25
private_st_PWGD_state();
26
27
/* Set defaults */
28
static void
29
s_PWGD_set_defaults(stream_state * st)
30
0
{
31
0
    stream_PWGD_state *const ss = (stream_PWGD_state *) st;
32
33
0
    (ss)->bpp = PWG_default_bpp;
34
0
    (ss)->width = PWG_default_width;
35
0
}
36
37
/* Initialize */
38
static int
39
s_PWGD_init(stream_state * st)
40
0
{
41
0
    stream_PWGD_state *const ss = (stream_PWGD_state *) st;
42
43
0
    (ss)->line_pos = 0;
44
0
    (ss)->line_rep = 0;
45
0
    (ss)->state = 0;
46
0
    (ss)->line_buffer = NULL;
47
48
0
    return 0;
49
0
}
50
51
/* Refill the buffer */
52
static int
53
s_PWGD_process(stream_state * st, stream_cursor_read * pr,
54
               stream_cursor_write * pw, bool last)
55
0
{
56
0
    stream_PWGD_state *const ss = (stream_PWGD_state *) st;
57
0
    register const byte *p = pr->ptr;
58
0
    register byte *q = pw->ptr;
59
0
    const byte *rlimit = pr->limit;
60
0
    byte *wlimit = pw->limit;
61
0
    int bpp = (ss->bpp+7)>>3;
62
0
    int wb = ss->width * bpp;
63
0
    int line_pos = ss->line_pos;
64
65
0
    if (ss->line_buffer == NULL) {
66
0
        ss->line_buffer =
67
0
                    gs_alloc_bytes_immovable(gs_memory_stable(ss->memory),
68
0
                                             wb,
69
0
                                             "s_PWGD_process(line_buffer)");
70
0
        if (ss->line_buffer == NULL)
71
0
            return ERRC;
72
0
    }
73
74
0
    while (1) {
75
0
        if (ss->state == 0) {
76
            /* Copy any buffered data out */
77
0
            if (ss->line_rep > 0) {
78
0
                int avail = wb - line_pos;
79
0
                if (avail > wlimit - q)
80
0
                    avail = wlimit - q;
81
0
                if (avail != 0)
82
0
                    memcpy(q+1, &ss->line_buffer[line_pos], avail);
83
0
                line_pos += avail;
84
0
                q += avail;
85
0
                if (line_pos == wb) {
86
0
                    line_pos = 0;
87
0
                    ss->line_rep--;
88
0
                }
89
0
                goto data_produced;
90
0
            }
91
            /* Now unpack data into the line buffer */
92
            /* Awaiting line repeat value */
93
0
            if (p == rlimit)
94
0
                goto need_data;
95
0
            ss->line_rep = (*++p) + 1;
96
0
            ss->state = 1; /* Wait for pixel repeat */
97
0
        }
98
0
        if (ss->state == 1) {
99
0
            int rep;
100
            /* Awaiting pixel repeat value */
101
0
            if (p == rlimit)
102
0
                goto need_data;
103
0
            rep = *++p;
104
0
            if (rep < 0x80) {
105
                /* Repeat the next pixel multiple times */
106
0
                ss->state = (rep+1) * bpp + 1;
107
0
                if (line_pos + ss->state - 1 > wb)
108
                    /* Too many repeats for this line! */
109
0
                    goto error;
110
0
            } else {
111
                /* Copy colors */
112
0
                ss->state = -(257 - rep) * bpp;
113
0
                if (line_pos + -ss->state > wb)
114
                    /* Too many pixels for this line! */
115
0
                    goto error;
116
0
            }
117
0
        }
118
0
        if (ss->state > 1) {
119
            /* Repeating a single pixel */
120
0
            int pixel_pos = line_pos % bpp;
121
0
            int avail = bpp - pixel_pos;
122
0
            if (avail > rlimit - p)
123
0
                avail = rlimit - p;
124
0
            if (avail != 0)
125
0
                memcpy(&ss->line_buffer[line_pos], p+1, avail);
126
0
            p += avail;
127
0
            line_pos += avail;
128
0
            pixel_pos += avail;
129
0
            ss->state -= avail;
130
0
            if (pixel_pos != bpp)
131
0
                goto need_data;
132
0
            while (ss->state > 1) {
133
0
                memcpy(&ss->line_buffer[line_pos], &ss->line_buffer[line_pos - bpp], bpp);
134
0
                line_pos += bpp;
135
0
                ss->state -= bpp;
136
0
            }
137
0
            if (line_pos == wb) {
138
0
                line_pos = 0;
139
0
                ss->state = 0;
140
0
            } else
141
0
                ss->state = 1;
142
0
        }
143
0
        if (ss->state < 0) {
144
            /* Copying literals */
145
0
            int avail = -ss->state;
146
0
            if (avail > rlimit - p)
147
0
                avail = rlimit - p;
148
0
            memcpy(&ss->line_buffer[line_pos], p + 1, avail);
149
0
            p += avail;
150
0
            ss->state += avail;
151
0
            line_pos += avail;
152
0
            if (ss->state)
153
0
                goto need_data;
154
0
            ss->state = 1;
155
0
        }
156
0
    }
157
0
need_data:
158
0
    {
159
0
        int status = 0; /* Need input data */
160
0
        if (0) {
161
0
error:
162
0
            status = ERRC;
163
0
        } else if (0) {
164
0
data_produced:
165
0
            status = 1; /* Need output space */
166
0
        }
167
0
        pr->ptr = p;
168
0
        pw->ptr = q;
169
0
        ss->line_pos = line_pos;
170
0
        return status;
171
0
    }
172
0
}
173
174
static void
175
s_PWGD_release(stream_state * st)
176
0
{
177
0
    stream_PWGD_state *const ss = (stream_PWGD_state *) st;
178
179
0
    gs_free_object(st->memory, ss->line_buffer, "PWGD(close)");
180
0
    ss->line_buffer = NULL;
181
0
}
182
183
/* Stream template */
184
const stream_template s_PWGD_template = {
185
    &st_PWGD_state, s_PWGD_init, s_PWGD_process, 1, 1, s_PWGD_release,
186
    s_PWGD_set_defaults
187
};