Coverage Report

Created: 2026-04-01 07:17

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