Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/scfd.c
Line
Count
Source
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
/* CCITTFax decoding filter */
18
#include "stdio_.h"   /* includes std.h */
19
#include "memory_.h"
20
#include "gdebug.h"
21
#include "strimpl.h"
22
#include "scf.h"
23
#include "scfx.h"
24
25
/* ------ CCITTFaxDecode ------ */
26
27
private_st_CFD_state();
28
29
111M
#define CFD_BUFFER_SLOP 4
30
31
static inline int
32
get_run(stream_CFD_state *ss, stream_cursor_read *pr, const cfd_node decode[],
33
    int initial_bits, int min_bits, int *runlen, const char *str);
34
35
static inline int
36
invert_data(stream_CFD_state *ss, stream_cursor_read *pr, int *rlen, byte black_byte);
37
38
static inline int
39
skip_data(stream_CFD_state *ss, stream_cursor_read *pr, int rlen);
40
41
/* Set default parameter values. */
42
static void
43
s_CFD_set_defaults(register stream_state * st)
44
1.92M
{
45
1.92M
    stream_CFD_state *const ss = (stream_CFD_state *) st;
46
47
1.92M
    s_CFD_set_defaults_inline(ss);
48
1.92M
}
49
50
/* Initialize CCITTFaxDecode filter */
51
static int
52
s_CFD_init(stream_state * st)
53
1.92M
{
54
1.92M
    stream_CFD_state *const ss = (stream_CFD_state *) st;
55
1.92M
    int raster = ss->raster =
56
1.92M
        ROUND_UP((ss->Columns + 7) >> 3, ss->DecodedByteAlign);
57
1.92M
    byte white = (ss->BlackIs1 ? 0 : 0xff);
58
59
1.92M
    if (raster < 0)
60
3
        return ERRC;
61
62
1.92M
    if (ss->Columns <= 0)
63
0
        return ERRC;
64
65
1.92M
    s_hcd_init_inline(ss);
66
    /* Because skip_white_pixels can look as many as 4 bytes ahead, */
67
    /* we need to allow 4 extra bytes at the end of the row buffers. */
68
1.92M
    ss->lbufstart = gs_alloc_bytes(st->memory, raster + CFD_BUFFER_SLOP * (size_t)2, "CFD lbuf");
69
1.92M
    ss->lprev = 0;
70
1.92M
    if (ss->lbufstart == 0)
71
0
        return ERRC;   /****** WRONG ******/
72
1.92M
    ss->lbuf = ss->lbufstart + CFD_BUFFER_SLOP;
73
1.92M
    memset(ss->lbufstart, 0xaa, CFD_BUFFER_SLOP);
74
1.92M
    memset(ss->lbuf, white, raster);
75
1.92M
    memset(ss->lbuf + raster, 0xaa, CFD_BUFFER_SLOP);  /* for Valgrind */
76
1.92M
    if (ss->K != 0) {
77
1.92M
        ss->lprevstart = gs_alloc_bytes(st->memory, raster + CFD_BUFFER_SLOP * (size_t)2, "CFD lprev");
78
1.92M
        if (ss->lprevstart == 0)
79
0
            return ERRC; /****** WRONG ******/
80
1.92M
        ss->lprev = ss->lprevstart + CFD_BUFFER_SLOP;
81
        /* Clear the initial reference line for 2-D encoding. */
82
1.92M
        memset(ss->lprev, white, raster);
83
        /* Ensure that the scan of the reference line will stop. */
84
1.92M
        memset(ss->lprev + raster, 0xaa, CFD_BUFFER_SLOP);
85
1.92M
        memset(ss->lprevstart, 0xaa, CFD_BUFFER_SLOP);
86
1.92M
    }
87
1.92M
    ss->k_left = min(ss->K, 0);
88
1.92M
    ss->run_color = 0;
89
1.92M
    ss->damaged_rows = 0;
90
1.92M
    ss->skipping_damage = false;
91
1.92M
    ss->cbit = 0;
92
1.92M
    ss->uncomp_run = 0;
93
1.92M
    ss->rows_left = (ss->Rows <= 0 || ss->EndOfBlock ? -1 : ss->Rows);
94
1.92M
    ss->row = 0;
95
1.92M
    ss->rpos = ss->wpos = -1;
96
1.92M
    ss->eol_count = 0;
97
1.92M
    ss->invert = white;
98
1.92M
    ss->min_left = 1;
99
1.92M
    return 0;
100
1.92M
}
101
102
/* Release the filter. */
103
static void
104
s_CFD_release(stream_state * st)
105
1.92M
{
106
1.92M
    stream_CFD_state *const ss = (stream_CFD_state *) st;
107
108
1.92M
    gs_free_object(st->memory, ss->lprevstart, "CFD lprev(close)");
109
1.92M
    gs_free_object(st->memory, ss->lbufstart, "CFD lbuf(close)");
110
1.92M
}
111
112
/* Declare the variables that hold the state. */
113
#define cfd_declare_state\
114
193M
        hcd_declare_state;\
115
193M
        register byte *q;\
116
193M
        int qbit
117
/* Load the state from the stream. */
118
#define cfd_load_state()\
119
331M
        hcd_load_state(),\
120
0
        q = ss->lbuf + ss->wpos, qbit = ss->cbit
121
/* Store the state back in the stream. */
122
#define cfd_store_state()\
123
331M
        hcd_store_state(),\
124
122M
        ss->wpos = q - ss->lbuf, ss->cbit = qbit
125
126
/* Macros to get blocks of bits from the input stream. */
127
/* Invariants: 0 <= bits_left <= bits_size; */
128
/* bits [bits_left-1..0] contain valid data. */
129
130
1.46M
#define avail_bits(n) hcd_bits_available(n)
131
370M
#define ensure_bits(n, outl) hcd_ensure_bits(n, outl)
132
401M
#define peek_bits(n) hcd_peek_bits(n)
133
1.46M
#define peek_var_bits(n) hcd_peek_var_bits(n)
134
333M
#define skip_bits(n) hcd_skip_bits(n)
135
136
/* Get a run from the stream. */
137
#ifdef DEBUG
138
#  define IF_DEBUG(expr) expr
139
#else
140
1.46M
#  define IF_DEBUG(expr) DO_NOTHING
141
#endif
142
143
static inline int get_run(stream_CFD_state *ss, stream_cursor_read *pr, const cfd_node decode[],
144
           int initial_bits, int min_bits, int *runlen, const char *str)
145
31.9M
{
146
31.9M
    cfd_declare_state;
147
31.9M
    const cfd_node *np;
148
31.9M
    int clen;
149
31.9M
    cfd_load_state();
150
151
31.9M
    HCD_ENSURE_BITS_ELSE(initial_bits) {
152
        /* We might still have enough bits for the specific code. */
153
1.86k
        if (bits_left < min_bits)
154
556
            goto outl;
155
1.31k
        np = &decode[hcd_peek_bits_left() << (initial_bits - bits_left)];
156
1.31k
        if ((clen = np->code_length) > bits_left)
157
688
            goto outl;
158
623
        goto locl;
159
1.31k
    }
160
31.9M
    np = &decode[peek_bits(initial_bits)];
161
31.9M
    if ((clen = np->code_length) > initial_bits) {
162
1.46M
            IF_DEBUG(uint init_bits = peek_bits(initial_bits));
163
1.46M
            if (!avail_bits(clen)) goto outl;
164
1.46M
            clen -= initial_bits;
165
1.46M
            skip_bits(initial_bits);
166
1.46M
            ensure_bits(clen, outl);                /* can't goto outl */
167
1.46M
            np = &decode[np->run_length + peek_var_bits(clen)];
168
1.46M
            if_debug4('W', "%s xcode=0x%x,%d rlen=%d\n", str,
169
1.46M
                      (init_bits << np->code_length) +
170
1.46M
                        peek_var_bits(np->code_length),
171
1.46M
                      initial_bits + np->code_length,
172
1.46M
                      np->run_length);
173
1.46M
            skip_bits(np->code_length);
174
30.4M
    } else {
175
30.4M
locl:
176
30.4M
       if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,
177
30.4M
                      peek_var_bits(clen), clen, np->run_length);
178
30.4M
       skip_bits(clen);
179
30.4M
    }
180
31.9M
    *runlen = np->run_length;
181
182
31.9M
    cfd_store_state();
183
31.9M
    return(0);
184
1.31k
outl:
185
1.31k
    cfd_store_state();
186
1.31k
    return(-1);
187
31.9M
}
188
189
190
/* Skip data bits for a white run. */
191
/* rlen is either less than 64, or a multiple of 64. */
192
static inline int skip_data(stream_CFD_state *ss, stream_cursor_read *pr, int rlen)
193
9.41M
{
194
9.41M
    cfd_declare_state;
195
9.41M
    cfd_load_state();
196
9.41M
    (void)rlimit;
197
198
9.41M
    if ( (qbit -= rlen) < 0 )
199
6.84M
    {
200
6.84M
        q -= qbit >> 3, qbit &= 7;
201
6.84M
        if ( rlen >= 64 ) {
202
367k
            cfd_store_state();
203
367k
            return(-1);
204
367k
        }
205
6.84M
    }
206
9.41M
    cfd_store_state();
207
9.05M
    return(0);
208
9.41M
}
209
210
211
/* Invert data bits for a black run. */
212
/* If rlen >= 64, execute makeup_action: this is to handle */
213
/* makeup codes efficiently, since these are always a multiple of 64. */
214
215
static inline int invert_data(stream_CFD_state *ss, stream_cursor_read *pr, int *rlen, byte black_byte)
216
96.1M
{
217
96.1M
    byte *qlim = ss->lbuf + ss->raster + CFD_BUFFER_SLOP;
218
96.1M
    cfd_declare_state;
219
96.1M
    cfd_load_state();
220
96.1M
    (void)rlimit;
221
222
96.1M
    if (q >= qlim || q < ss->lbufstart) {
223
0
        return(-1);
224
0
    }
225
226
96.1M
    if ( (*rlen) > qbit )
227
59.7M
    {
228
59.7M
        if (q + ((*rlen - qbit) >> 3) > qlim) {
229
7
            return(-1);
230
7
        }
231
232
59.7M
        if (q >= ss->lbuf) {
233
58.0M
          *q++ ^= (1 << qbit) - 1;
234
58.0M
        }
235
1.74M
        else {
236
1.74M
            q++;
237
1.74M
        }
238
59.7M
        (*rlen) -= qbit;
239
240
59.7M
        if (q + ((*rlen) >> 3) >= qlim) {
241
11
            return(-1);
242
11
        }
243
244
59.7M
        switch ( (*rlen) >> 3 )
245
59.7M
        {
246
325k
          case 7:         /* original rlen possibly >= 64 */
247
325k
                  if ( (*rlen) + qbit >= 64 ) {
248
180k
                    goto d;
249
180k
                  }
250
145k
                  *q++ = black_byte;
251
421k
          case 6: *q++ = black_byte;
252
765k
          case 5: *q++ = black_byte;
253
1.35M
          case 4: *q++ = black_byte;
254
2.45M
          case 3: *q++ = black_byte;
255
5.70M
          case 2: *q++ = black_byte;
256
15.0M
          case 1: *q = black_byte;
257
15.0M
              (*rlen) &= 7;
258
15.0M
              if ( !(*rlen) ) {
259
2.65M
                  qbit = 0;
260
2.65M
                  break;
261
2.65M
              }
262
12.3M
              q++;
263
56.3M
          case 0:                 /* know rlen != 0 */
264
56.3M
              qbit = 8 - (*rlen);
265
56.3M
              *q ^= 0xff << qbit;
266
56.3M
              break;
267
611k
          default:        /* original rlen >= 64 */
268
792k
d:            memset(q, black_byte, (*rlen) >> 3);
269
792k
              q += (*rlen) >> 3;
270
792k
              (*rlen) &= 7;
271
792k
              if ( !(*rlen) ) {
272
112k
                qbit = 0;
273
112k
                q--;
274
112k
              }
275
679k
              else {
276
679k
                qbit = 8 - (*rlen);
277
679k
                *q ^= 0xff << qbit;
278
679k
              }
279
792k
              cfd_store_state();
280
792k
              return(-1);
281
59.7M
          }
282
59.7M
    }
283
36.3M
    else {
284
36.3M
            qbit -= (*rlen),
285
36.3M
            *q ^= ((1 << (*rlen)) - 1) << qbit;
286
287
36.3M
    }
288
96.1M
    cfd_store_state();
289
95.3M
    return(0);
290
96.1M
}
291
292
293
/* Buffer refill for CCITTFaxDecode filter */
294
static int cf_decode_eol(stream_CFD_state *, stream_cursor_read *);
295
static int cf_decode_1d(stream_CFD_state *, stream_cursor_read *);
296
static int cf_decode_2d(stream_CFD_state *, stream_cursor_read *);
297
static int cf_decode_uncompressed(stream_CFD_state *, stream_cursor_read *);
298
static int
299
s_CFD_process(stream_state * st, stream_cursor_read * pr,
300
              stream_cursor_write * pw, bool last)
301
1.98M
{
302
1.98M
    stream_CFD_state *const ss = (stream_CFD_state *) st;
303
1.98M
    int wstop = ss->raster - 1;
304
1.98M
    int eol_count = ss->eol_count;
305
1.98M
    int k_left = ss->k_left;
306
1.98M
    int rows_left = ss->rows_left;
307
1.98M
    int status = 0;
308
309
#ifdef DEBUG
310
    const byte *rstart = pr->ptr;
311
    const byte *wstart = pw->ptr;
312
313
#endif
314
315
    /* Update the pointers we actually use, in case GC moved the buffer */
316
1.98M
    ss->lbuf = ss->lbufstart + CFD_BUFFER_SLOP;
317
1.98M
    ss->lprev = ss->lprevstart + CFD_BUFFER_SLOP;
318
319
58.0M
top:
320
#ifdef DEBUG
321
    {
322
        hcd_declare_state;
323
        hcd_load_state();
324
        (void)rlimit;
325
        if_debug8m('w', ss->memory,
326
                   "[w]CFD_process top: eol_count=%d, k_left=%d, rows_left=%d\n"
327
                   "    bits="PRI_INTPTR", bits_left=%d, read %u, wrote %u%s\n",
328
                   eol_count, k_left, rows_left,
329
                   (intptr_t) bits, bits_left,
330
                   (uint) (p - rstart), (uint) (pw->ptr - wstart),
331
                   (ss->skipping_damage ? ", skipping damage" : ""));
332
    }
333
#endif
334
58.0M
    if (ss->skipping_damage) { /* Skip until we reach an EOL. */
335
0
        hcd_declare_state;
336
0
        int skip;
337
0
        (void)rlimit;
338
339
0
        status = 0;
340
0
        do {
341
0
            switch ((skip = cf_decode_eol(ss, pr))) {
342
0
                default:  /* not EOL */
343
0
                    hcd_load_state();
344
0
                    skip_bits(-skip);
345
0
                    hcd_store_state();
346
0
                    continue;
347
0
                case 0: /* need more input */
348
0
                    goto out;
349
0
                case 1: /* EOL */
350
0
                    {   /* Back up over the EOL. */
351
0
                        hcd_load_state();
352
0
                        bits_left += run_eol_code_length;
353
0
                        hcd_store_state();
354
0
                    }
355
0
                    ss->skipping_damage = false;
356
0
            }
357
0
        }
358
0
        while (ss->skipping_damage);
359
0
        ss->damaged_rows++;
360
0
    }
361
    /*
362
     * Check for a completed input scan line.  This isn't quite as
363
     * simple as it seems, because we could have run out of input data
364
     * between a makeup code and a 0-length termination code, or in a
365
     * 2-D line before a final horizontal code with a 0-length second
366
     * run.  There's probably a way to think about this situation that
367
     * doesn't require a special check, but I haven't found it yet.
368
     */
369
58.0M
    if (ss->wpos == wstop && ss->cbit <= (-ss->Columns & 7) &&
370
56.1M
        (k_left == 0 ? !(ss->run_color & ~1) : ss->run_color == 0)
371
58.0M
        ) {     /* Check for completed data to be copied to the client. */
372
        /* (We could avoid the extra copy step for 1-D, but */
373
        /* it's simpler not to, and it doesn't cost much.) */
374
56.1M
        if (ss->rpos < ss->wpos) {
375
56.1M
            stream_cursor_read cr;
376
377
56.1M
            cr.ptr = ss->lbuf + ss->rpos;
378
56.1M
            cr.limit = ss->lbuf + ss->wpos;
379
56.1M
            status = stream_move(&cr, pw);
380
56.1M
            ss->rpos = cr.ptr - ss->lbuf;
381
56.1M
            if (status)
382
50.3k
                goto out;
383
56.1M
        }
384
56.0M
        ss->row++;
385
56.0M
        if (rows_left > 0 && --rows_left == 0)
386
269
            goto ck_eol;  /* handle EOD if it is present */
387
56.0M
        if (ss->K != 0) {
388
56.0M
            byte *prev_bits = ss->lprev;
389
56.0M
            byte *prev_start = ss->lprevstart;
390
391
56.0M
            ss->lprev = ss->lbuf;
392
56.0M
            ss->lprevstart = ss->lbufstart;
393
56.0M
            ss->lbuf = prev_bits;
394
56.0M
            ss->lbufstart = prev_start;
395
56.0M
            if (ss->K > 0)
396
2.99k
                k_left = (k_left == 0 ? ss->K : k_left) - 1;
397
56.0M
        }
398
56.0M
        ss->rpos = ss->wpos = -1;
399
56.0M
        ss->eol_count = eol_count = 0;
400
56.0M
        ss->cbit = 0;
401
56.0M
        ss->invert = (ss->BlackIs1 ? 0 : 0xff);
402
56.0M
        memset(ss->lbuf, ss->invert, wstop + 1);
403
56.0M
        ss->run_color = 0;
404
        /*
405
         * If EndOfLine is true, we want to include the byte padding
406
         * in the string of initial zeros in the EOL.  If EndOfLine
407
         * is false, we aren't sure what we should do....
408
         */
409
56.0M
        if (ss->EncodedByteAlign && !ss->EndOfLine)
410
0
            ss->bits_left &= ~7;
411
56.0M
    }
412
    /* If we're between scan lines, scan for EOLs. */
413
58.0M
    if (ss->wpos < 0) {
414
            /*
415
             * According to Adobe, the decoder should always check for
416
             * the EOD sequence, regardless of EndOfBlock: the Red Book's
417
             * documentation of EndOfBlock is wrong.
418
             */
419
58.0M
ck_eol:
420
59.9M
        while ((status = cf_decode_eol(ss, pr)) > 0) {
421
3.88M
            if_debug0m('w', ss->memory, "[w]EOL\n");
422
            /* If we are in a Group 3 mixed regime, */
423
            /* check the next bit for 1- vs. 2-D. */
424
3.88M
            if (ss->K > 0) {
425
3.34k
                hcd_declare_state;
426
3.34k
                hcd_load_state();
427
3.34k
                ensure_bits(1, out); /* can't fail */
428
3.34k
                k_left = (peek_bits(1) ? 0 : 1);
429
3.34k
                skip_bits(1);
430
3.34k
                hcd_store_state();
431
3.34k
            }
432
3.88M
            ++eol_count;
433
3.88M
            if (eol_count == (ss->K < 0 ? 2 : 6)) {
434
1.92M
                status = EOFC;
435
1.92M
                goto out;
436
1.92M
            }
437
3.88M
        }
438
56.0M
        if (rows_left == 0) {
439
266
            status = EOFC;
440
266
            goto out;
441
266
        }
442
56.0M
        if (status == 0)  /* input empty while scanning EOLs */
443
3.12k
            goto out;
444
56.0M
        switch (eol_count) {
445
56.0M
            case 0:
446
56.0M
                if (ss->EndOfLine) { /* EOL is required, but none is present. */
447
0
                    status = ERRC;
448
0
                    goto check;
449
0
                }
450
56.0M
            case 1:
451
56.0M
                break;
452
6
            default:
453
6
                status = ERRC;
454
6
                goto check;
455
56.0M
        }
456
56.0M
    }
457
    /* Now decode actual data. */
458
56.0M
    if (k_left < 0) {
459
56.0M
        if_debug0m('w', ss->memory, "[w2]new row\n");
460
56.0M
        status = cf_decode_2d(ss, pr);
461
56.0M
    } else if (k_left == 0) {
462
38.3k
        if_debug0m('w', ss->memory, "[w1]new row\n");
463
38.3k
        status = cf_decode_1d(ss, pr);
464
38.3k
    } else {
465
2.91k
        if_debug1m('w', ss->memory, "[w1]new 2-D row, k_left=%d\n", k_left);
466
2.91k
        status = cf_decode_2d(ss, pr);
467
2.91k
    }
468
56.0M
    if_debug3m('w', ss->memory, "[w]CFD status = %d, wpos = %d, cbit = %d\n",
469
56.0M
               status, ss->wpos, ss->cbit);
470
56.0M
  check:switch (status) {
471
56.0M
        case 1:   /* output full */
472
56.0M
            goto top;
473
2.10k
        case ERRC:
474
            /* Check for special handling of damaged rows. */
475
2.10k
            if (ss->damaged_rows >= ss->DamagedRowsBeforeError ||
476
0
                !(ss->EndOfLine && ss->K >= 0)
477
2.10k
                )
478
2.10k
                break;
479
            /* Substitute undamaged data if appropriate. */
480
            /****** NOT IMPLEMENTED YET ******/
481
0
            {
482
0
                ss->wpos = wstop;
483
0
                ss->cbit = -ss->Columns & 7;
484
0
                ss->run_color = 0;
485
0
            }
486
0
            ss->skipping_damage = true;
487
0
            goto top;
488
1.81k
        default:
489
1.81k
            ss->damaged_rows = 0; /* finished a good row */
490
56.0M
    }
491
1.98M
  out:ss->k_left = k_left;
492
1.98M
    ss->rows_left = rows_left;
493
1.98M
    ss->eol_count = eol_count;
494
1.98M
    if (ss->ErrsAsEOD && status < 0)
495
0
        return EOFC;
496
1.98M
    return status;
497
1.98M
}
498
499
/*
500
 * Decode a leading EOL, if any.
501
 * If an EOL is present, skip over it and return 1;
502
 * if no EOL is present, read no input and return -N, where N is the
503
 * number of initial bits that can be skipped in the search for an EOL;
504
 * if more input is needed, return 0.
505
 * Note that if we detected an EOL, we know that we can back up over it;
506
 * if we detected an N-bit non-EOL, we know that at least N bits of data
507
 * are available in the buffer.
508
 */
509
static int
510
cf_decode_eol(stream_CFD_state * ss, stream_cursor_read * pr)
511
59.9M
{
512
59.9M
    hcd_declare_state;
513
59.9M
    int zeros;
514
59.9M
    int look_ahead;
515
516
59.9M
    hcd_load_state();
517
132M
    for (zeros = 0; zeros < run_eol_code_length - 1; zeros++) {
518
128M
        ensure_bits(1, out);
519
128M
        if (peek_bits(1))
520
56.0M
            return -(zeros + 1);
521
72.8M
        skip_bits(1);
522
72.8M
    }
523
    /* We definitely have an EOL.  Skip further zero bits. */
524
3.88M
    look_ahead = (ss->K > 0 ? 2 : 1);
525
3.89M
    for (;;) {
526
3.89M
        ensure_bits(look_ahead, back);
527
3.89M
        if (peek_bits(1))
528
3.88M
            break;
529
917
        skip_bits(1);
530
917
    }
531
3.88M
    skip_bits(1);
532
3.88M
    hcd_store_state();
533
3.88M
    return 1;
534
0
  back:     /*
535
                                 * We ran out of data while skipping zeros.
536
                                 * We know we are at a byte boundary, and have just skipped
537
                                 * at least run_eol_code_length - 1 zeros.  However,
538
                                 * bits_left may be 1 if look_ahead == 2.
539
                                 */
540
0
    bits &= (1 << bits_left) - 1;
541
0
    bits_left += run_eol_code_length - 1;
542
0
    hcd_store_state();
543
3.12k
  out:return 0;
544
0
}
545
546
/* Decode a 1-D scan line. */
547
static int
548
cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr)
549
38.3k
{
550
38.3k
    cfd_declare_state;
551
38.3k
    byte black_byte = (ss->BlackIs1 ? 0xff : 0);
552
38.3k
    int end_bit = -ss->Columns & 7;
553
38.3k
    byte *stop = ss->lbuf - 1 + ss->raster;
554
38.3k
    int run_color = ss->run_color;
555
38.3k
    int status;
556
38.3k
    int bcnt;
557
38.3k
    (void)rlimit;
558
559
38.3k
    cfd_load_state();
560
38.3k
    if_debug1m('w', ss->memory, "[w1]entry run_color = %d\n", ss->run_color);
561
38.3k
    if (run_color > 0)
562
257
        goto db;
563
38.1k
    else
564
38.1k
        goto dw;
565
1.79M
#define q_at_stop() (q >= stop && (qbit <= end_bit || q > stop))
566
881k
    while (1)
567
881k
    {
568
881k
        run_color = 0;
569
881k
        if (q_at_stop())
570
4.32k
            goto done;
571
572
915k
  dw:   /* Decode a white run. */
573
1.17M
        do {
574
1.17M
            cfd_store_state();
575
1.17M
            status = get_run(ss, pr, cf_white_decode, cfd_white_initial_bits,
576
1.17M
                             cfd_white_min_bits, &bcnt, "[w1]white");
577
1.17M
            cfd_load_state();
578
1.17M
            if (status < 0) {
579
                /* We already set run_color to 0 or -1. */
580
475
                status = 0;
581
475
                goto out;
582
475
            }
583
584
1.17M
            if (bcnt < 0) {   /* exceptional situation */
585
36
                switch (bcnt) {
586
0
                    case run_uncompressed: /* Uncompressed data. */
587
0
                        cfd_store_state();
588
0
                        bcnt = cf_decode_uncompressed(ss, pr);
589
0
                        if (bcnt < 0)
590
0
                            return bcnt;
591
0
                        cfd_load_state();
592
0
                        if (bcnt)
593
0
                            goto db;
594
0
                        else
595
0
                            continue; /* Restart decoding white */
596
                        /*case run_error: */
597
                        /*case run_zeros: *//* Premature end-of-line. */
598
36
                    default:
599
36
                        status = ERRC;
600
36
                        goto out;
601
36
                }
602
36
            }
603
604
1.17M
            cfd_store_state();
605
1.17M
            status = skip_data(ss, pr, bcnt);
606
1.17M
            cfd_load_state();
607
1.17M
            if (status < 0) {
608
                /* If we run out of data after a makeup code, */
609
                /* note that we are still processing a white run. */
610
261k
                run_color = -1;
611
261k
            }
612
1.17M
        } while (status < 0);
613
614
915k
        if (q_at_stop()) {
615
33.2k
            run_color = 0;    /* not inside a run */
616
37.5k
  done:
617
37.5k
            if (q > stop || qbit < end_bit)
618
261
                status = ERRC;
619
37.2k
            else
620
37.2k
                status = 1;
621
37.5k
            break;
622
33.2k
        }
623
881k
        run_color = 1;
624
625
882k
  db:   /* Decode a black run. */
626
882k
        do {
627
882k
            cfd_store_state();
628
882k
            status = get_run(ss, pr, cf_black_decode, cfd_black_initial_bits,
629
882k
                             cfd_black_min_bits, &bcnt, "[w1]black");
630
882k
            cfd_load_state();
631
882k
            if (status < 0) {
632
                /* We already set run_color to 1 or 2. */
633
257
                status = 0;
634
257
                goto out;
635
257
            }
636
637
882k
            if (bcnt < 0) {  /* All exceptional codes are invalid here. */
638
                /****** WRONG, uncompressed IS ALLOWED ******/
639
43
                status = ERRC;
640
43
                goto out;
641
43
            }
642
643
            /* Invert bits designated by black run. */
644
882k
            cfd_store_state();
645
882k
            status = invert_data(ss, pr, &bcnt, black_byte);
646
882k
            cfd_load_state();
647
882k
            if (status < 0) {
648
                /* If we run out of data after a makeup code, */
649
                /* note that we are still processing a black run. */
650
585
                run_color = 2;
651
585
            }
652
882k
        } while (status < 0);
653
882k
    }
654
655
38.3k
out:
656
38.3k
    cfd_store_state();
657
38.3k
    ss->run_color = run_color;
658
38.3k
    if_debug1m('w', ss->memory, "[w1]exit run_color = %d\n", run_color);
659
38.3k
    return status;
660
0
}
661
662
/* Decode a 2-D scan line. */
663
static int
664
cf_decode_2d(stream_CFD_state * ss, stream_cursor_read * pr)
665
56.0M
{
666
56.0M
    cfd_declare_state;
667
56.0M
    byte invert_white = (ss->BlackIs1 ? 0 : 0xff);
668
56.0M
    byte black_byte = ~invert_white;
669
56.0M
    byte invert = ss->invert;
670
56.0M
    int end_count = -ss->Columns & 7;
671
56.0M
    uint raster = ss->raster;
672
56.0M
    byte *q0 = ss->lbuf;
673
56.0M
    byte *prev_q01 = ss->lprev + 1;
674
56.0M
    byte *endptr = q0 - 1 + raster;
675
56.0M
    int init_count = raster << 3;
676
56.0M
    register int count;
677
56.0M
    int rlen;
678
56.0M
    int status;
679
680
56.0M
    cfd_load_state();
681
56.0M
    count = ((endptr - q) << 3) + qbit;
682
56.0M
    endptr[1] = 0xa0;   /* a byte with some 0s and some 1s, */
683
    /* to ensure run scan will stop */
684
56.0M
    if_debug1m('W', ss->memory, "[w2]raster=%d\n", raster);
685
56.0M
    switch (ss->run_color) {
686
43
        case -2:
687
43
            ss->run_color = 0;
688
43
            goto hww;
689
128
        case -1:
690
128
            ss->run_color = 0;
691
128
            goto hbw;
692
102
        case 1:
693
102
            ss->run_color = 0;
694
102
            goto hwb;
695
26
        case 2:
696
26
            ss->run_color = 0;
697
26
            goto hbb;
698
            /*case 0: */
699
56.0M
    }
700
701
    /* top of decode loop */
702
292M
    while (1)
703
292M
    {
704
292M
        if (count <= end_count) {
705
56.0M
            status = (count < end_count ? ERRC : 1);
706
56.0M
            goto out;
707
56.0M
        }
708
        /* If invert == invert_white, white and black have their */
709
        /* correct meanings; if invert == ~invert_white, */
710
        /* black and white are interchanged. */
711
292M
        if_debug1m('W', ss->memory, "[w2]%4d:\n", count);
712
#ifdef DEBUG
713
        /* Check the invariant between q, qbit, and count. */
714
        {
715
            int pcount = (endptr - q) * 8 + qbit;
716
717
            if (pcount != count)
718
                dmlprintf2(ss->memory, "[w2]Error: count=%d pcount=%d\n",
719
                           count, pcount);
720
        }
721
#endif
722
        /*
723
         * We could just use get_run here, but we can do better.  However,
724
         * we must be careful to handle the case where the very last codes
725
         * in the input stream are 1-bit "vertical 0" codes: we can't just
726
         * use ensure_bits(3, ...) and go to get more data if it fails.
727
         */
728
236M
        ensure_bits(3, out3);
729
439M
#define vertical_0 (countof(cf2_run_vertical) / 2)
730
236M
        switch (peek_bits(3)) {
731
173M
        default /*4..7*/ :  /* vertical(0) */
732
173M
            if (0) {
733
718
 out3:
734
                /* Unless it's a 1-bit "vertical 0" code, exit. */
735
718
                if (!(bits_left > 0 && peek_bits(1)))
736
484
                    goto out0;
737
718
            }
738
173M
            skip_bits(1);
739
173M
            rlen = vertical_0;
740
173M
            break;
741
22.8M
        case 2:   /* vertical(+1) */
742
22.8M
            skip_bits(3);
743
22.8M
            rlen = vertical_0 + 1;
744
22.8M
            break;
745
18.9M
        case 3:   /* vertical(-1) */
746
18.9M
            skip_bits(3);
747
18.9M
            rlen = vertical_0 - 1;
748
18.9M
            break;
749
8.13M
        case 1:   /* horizontal */
750
8.13M
            skip_bits(3);
751
8.13M
            if (invert == invert_white) {
752
                /* We handle horizontal decoding here, so that we can
753
                 * branch back into it if we run out of input data. */
754
                /* White, then black. */
755
5.07M
  hww:
756
5.13M
                do {
757
5.13M
                    cfd_store_state();
758
5.13M
                    status = get_run(ss, pr, cf_white_decode,
759
5.13M
                                     cfd_white_initial_bits,
760
5.13M
                                     cfd_white_min_bits, &rlen, " white");
761
5.13M
                    cfd_load_state();
762
5.13M
                    if (status < 0) {
763
58
                        ss->run_color = -2;
764
58
                        goto out0;
765
58
                    }
766
767
5.13M
                    if ((count -= rlen) < end_count) {
768
159
                        status = ERRC;
769
159
                        goto out;
770
159
                    }
771
5.13M
                    if (rlen < 0) goto rlen_lt_zero;
772
773
5.13M
                    cfd_store_state();
774
5.13M
                    status = skip_data(ss, pr, rlen);
775
5.13M
                    cfd_load_state();
776
5.13M
                } while (status < 0);
777
778
                /* Handle the second half of a white-black horizontal code. */
779
5.07M
  hwb:
780
5.12M
                do {
781
5.12M
                    cfd_store_state();
782
5.12M
                    status = get_run(ss, pr, cf_black_decode,
783
5.12M
                                     cfd_black_initial_bits,
784
5.12M
                                     cfd_black_min_bits, &rlen, " black");
785
5.12M
                    cfd_load_state();
786
5.12M
                    if (status < 0){
787
123
                        ss->run_color = 1;
788
123
                        goto out0;
789
123
                    }
790
791
5.12M
                    if ((count -= rlen) < end_count) {
792
83
                        status = ERRC;
793
83
                        goto out;
794
83
                    }
795
5.12M
                    if (rlen < 0) goto rlen_lt_zero;
796
797
5.12M
                    cfd_store_state();
798
5.12M
                    status = invert_data(ss, pr, &rlen, black_byte);
799
5.12M
                    cfd_load_state();
800
5.12M
                } while (status < 0);
801
5.07M
            } else {
802
                /* Black, then white. */
803
3.05M
  hbb:
804
3.08M
                do {
805
3.08M
                    cfd_store_state();
806
3.08M
                    status = get_run(ss, pr, cf_black_decode,
807
3.08M
                                     cfd_black_initial_bits,
808
3.08M
                                     cfd_black_min_bits, &rlen, " black");
809
3.08M
                    cfd_load_state();
810
3.08M
                    if (status < 0) {
811
26
                        ss->run_color = 2;
812
26
                        goto out0;
813
26
                    }
814
815
3.08M
                    if ((count -= rlen) < end_count) {
816
129
                        status = ERRC;
817
129
                        goto out;
818
129
                    }
819
3.08M
                    if (rlen < 0) goto rlen_lt_zero;
820
821
3.08M
                    cfd_store_state();
822
3.08M
                    status = invert_data(ss, pr, &rlen, black_byte);
823
3.08M
                    cfd_load_state();
824
3.08M
                }
825
3.08M
                while (status < 0);
826
827
                /* Handle the second half of a black-white horizontal code. */
828
3.05M
  hbw:
829
3.10M
                do {
830
3.10M
                    cfd_store_state();
831
3.10M
                    status = get_run(ss, pr, cf_white_decode,
832
3.10M
                                     cfd_white_initial_bits,
833
3.10M
                                     cfd_white_min_bits, &rlen, " white");
834
3.10M
                    cfd_load_state();
835
3.10M
                    if (status < 0) {
836
138
                        ss->run_color = -1;
837
138
                        goto out0;
838
138
                    }
839
840
3.10M
                    if ((count -= rlen) < end_count) {
841
312
                        status = ERRC;
842
312
                        goto out;
843
312
                    }
844
3.10M
                    if (rlen < 0) goto rlen_lt_zero;
845
846
3.10M
                    cfd_store_state();
847
3.10M
                    status = skip_data(ss, pr, rlen);
848
3.10M
                    cfd_load_state();
849
3.10M
                } while (status < 0);
850
3.05M
            }
851
8.13M
            continue; /* jump back to top of decode loop */
852
13.4M
        case 0:   /* everything else */
853
13.4M
            cfd_store_state();
854
13.4M
            status = get_run(ss, pr, cf_2d_decode, cfd_2d_initial_bits,
855
13.4M
                             cfd_2d_min_bits, &rlen, "[w2]");
856
13.4M
            cfd_load_state();
857
13.4M
            if (status < 0) {
858
235
                goto out0;
859
235
            }
860
861
            /* rlen may be run2_pass, run_uncompressed, or */
862
            /* 0..countof(cf2_run_vertical)-1. */
863
13.4M
            if (rlen < 0) {
864
3.58M
rlen_lt_zero:
865
3.58M
                switch (rlen) {
866
3.58M
                case run2_pass:
867
3.58M
                    break;
868
9
                case run_uncompressed:
869
9
                {
870
9
                    int which;
871
872
9
                    cfd_store_state();
873
9
                    which = cf_decode_uncompressed(ss, pr);
874
9
                    if (which < 0) {
875
9
                        status = which;
876
9
                        goto out;
877
9
                    }
878
9
                    cfd_load_state();
879
/****** ADJUST count ******/
880
0
                    invert = (which ? ~invert_white : invert_white);
881
0
                    continue; /* jump back to top of decode loop */
882
9
                }
883
329
                default:  /* run_error, run_zeros */
884
329
                    status = ERRC;
885
329
                    goto out;
886
3.58M
                }
887
3.58M
            }
888
236M
        }
889
        /* Interpreting the run requires scanning the */
890
        /* previous ('reference') line. */
891
228M
        {
892
228M
            int prev_count = count;
893
228M
            byte prev_data;
894
228M
            int dlen;
895
228M
            static const byte count_bit[8] =
896
228M
                                   {0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40};
897
228M
            byte *prev_q = prev_q01 + (q - q0);
898
228M
            int plen;
899
900
228M
            if (!(count & 7))
901
74.1M
                prev_q++;   /* because of skip macros */
902
228M
            prev_data = prev_q[-1] ^ invert;
903
            /* Find the b1 transition. */
904
228M
            if ((prev_data & count_bit[prev_count & 7]) &&
905
28.9M
                (prev_count < init_count || invert != invert_white)
906
228M
                ) {     /* Look for changing white first. */
907
27.2M
                if_debug1m('W', ss->memory, " data=0x%x", prev_data);
908
27.2M
                skip_black_pixels(prev_data, prev_q,
909
27.2M
                                  prev_count, invert, plen);
910
27.2M
                if (prev_count < end_count)    /* overshot */
911
9.83k
                    prev_count = end_count;
912
27.2M
                if_debug1m('W', ss->memory, " b1 other=%d", prev_count);
913
27.2M
            }
914
228M
            if (prev_count != end_count) {
915
228M
                if_debug1m('W', ss->memory, " data=0x%x", prev_data);
916
228M
                skip_white_pixels(prev_data, prev_q,
917
228M
                                  prev_count, invert, plen);
918
228M
                if (prev_count < end_count)    /* overshot */
919
340k
                    prev_count = end_count;
920
228M
                if_debug1m('W', ss->memory, " b1 same=%d", prev_count);
921
228M
            }
922
            /* b1 = prev_count; */
923
228M
            if (rlen == run2_pass) { /* Pass mode.  Find b2. */
924
3.58M
                if (prev_count != end_count) {
925
3.58M
                    if_debug1m('W', ss->memory, " data=0x%x", prev_data);
926
3.58M
                    skip_black_pixels(prev_data, prev_q,
927
3.58M
                                      prev_count, invert, plen);
928
3.58M
                    if (prev_count < end_count)  /* overshot */
929
140
                        prev_count = end_count;
930
3.58M
                }
931
                /* b2 = prev_count; */
932
3.58M
                if_debug2m('W', ss->memory, " b2=%d, pass %d\n",
933
3.58M
                           prev_count, count - prev_count);
934
224M
            } else {   /* Vertical coding. */
935
                /* Remember that count counts *down*. */
936
224M
                prev_count += rlen - vertical_0; /* a1 */
937
224M
                if_debug2m('W', ss->memory, " vertical %d -> %d\n",
938
224M
                           (int)(rlen - vertical_0), prev_count);
939
224M
            }
940
            /* Now either invert or skip from count */
941
            /* to prev_count, and reset count. */
942
228M
            if (invert == invert_white) { /* Skip data bits. */
943
141M
                q = endptr - (prev_count >> 3);
944
141M
                qbit = prev_count & 7;
945
141M
            } else {   /* Invert data bits. */
946
87.0M
                dlen = count - prev_count;
947
948
87.0M
                cfd_store_state();
949
87.0M
                (void)invert_data(ss, pr, &dlen, black_byte);
950
87.0M
                cfd_load_state();
951
87.0M
            }
952
228M
            count = prev_count;
953
228M
            if (rlen >= 0)    /* vertical mode */
954
224M
                invert = ~invert; /* polarity changes */
955
228M
        }
956
        /* jump back to top of decode loop */
957
228M
    }
958
959
1.06k
  out0:status = 0;
960
    /* falls through */
961
56.0M
  out:cfd_store_state();
962
56.0M
    ss->invert = invert;
963
    /* Ignore an error (missing EOFB/RTC when EndOfBlock == true) */
964
    /* if we have finished all rows. */
965
56.0M
    if (status == ERRC && ss->Rows > 0 && ss->row > ss->Rows)
966
20
        status = EOFC;
967
56.0M
    return status;
968
1.06k
}
969
970
#if 1       /*************** */
971
static int
972
cf_decode_uncompressed(stream_CFD_state * ss, stream_cursor_read * pr)
973
9
{
974
9
    return ERRC;
975
9
}
976
#else /*************** */
977
978
/* Decode uncompressed data. */
979
/* (Not tested: no sample data available!) */
980
/****** DOESN'T CHECK FOR OVERFLOWING SCAN LINE ******/
981
static int
982
cf_decode_uncompressed(stream * s)
983
{
984
    cfd_declare_state;
985
    const cfd_node *np;
986
    int clen, rlen;
987
988
    cfd_load_state();
989
    while (1) {
990
        ensure_bits(cfd_uncompressed_initial_bits, NOOUT);
991
        np = &cf_uncompressed_decode[peek_bits(cfd_uncompressed_initial_bits)];
992
        clen = np->code_length;
993
        rlen = np->run_length;
994
        if (clen > cfd_uncompressed_initial_bits) { /* Must be an exit code. */
995
            break;
996
        }
997
        if (rlen == cfd_uncompressed_initial_bits) {  /* Longest representable white run */
998
            if_debug1m('W', s->memory, "[wu]%d\n", rlen);
999
            if ((qbit -= cfd_uncompressed_initial_bits) < 0)
1000
                qbit += 8, q++;
1001
        } else {
1002
            if_debug1m('W', s->memory, "[wu]%d+1\n", rlen);
1003
            if (qbit -= rlen < 0)
1004
                qbit += 8, q++;
1005
            *q ^= 1 << qbit;
1006
        }
1007
        skip_bits(clen);
1008
    }
1009
    clen -= cfd_uncompressed_initial_bits;
1010
    skip_bits(cfd_uncompressed_initial_bits);
1011
    ensure_bits(clen, NOOUT);
1012
    np = &cf_uncompressed_decode[rlen + peek_var_bits(clen)];
1013
    rlen = np->run_length;
1014
    skip_bits(np->code_length);
1015
    if_debug1m('w', s->memory, "[wu]exit %d\n", rlen);
1016
    if (rlen >= 0) {    /* Valid exit code, rlen = 2 * run length + next polarity */
1017
        if ((qbit -= rlen >> 1) < 0)
1018
            qbit += 8, q++;
1019
        rlen &= 1;
1020
    }
1021
  out:        /******* WRONG ******/
1022
    cfd_store_state();
1023
    return rlen;
1024
}
1025
1026
#endif /*************** */
1027
1028
/* Stream template */
1029
const stream_template s_CFD_template =
1030
{&st_CFD_state, s_CFD_init, s_CFD_process, 1, 1, s_CFD_release,
1031
 s_CFD_set_defaults
1032
};