Coverage Report

Created: 2026-07-24 07:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/spdiff.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 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
/* Pixel differencing filters */
18
#include "stdio_.h"   /* should be std.h, but needs NULL */
19
#include "memory_.h"
20
#include "strimpl.h"
21
#include "spdiffx.h"
22
#include "gserrors.h"
23
#include "gxdevice.h"
24
25
/* ------ PixelDifferenceEncode/Decode ------ */
26
27
private_st_PDiff_state();
28
29
/* Define values for case dispatch. */
30
15
#define cBits1 0
31
15
#define cBits2 5
32
15
#define cBits4 10
33
15.2k
#define cBits8 15
34
15
#define cBits16 20
35
30
#define cEncode 0
36
15.2k
#define cDecode 25
37
38
/* Set defaults */
39
static void
40
s_PDiff_set_defaults(stream_state * st)
41
15
{
42
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
43
44
15
    s_PDiff_set_defaults_inline(ss);
45
15
}
46
47
/* Common (re)initialization. */
48
static int
49
s_PDiff_reinit(stream_state * st)
50
15
{
51
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
52
53
15
    ss->row_left = 0;
54
15
    return 0;
55
15
}
56
57
/* Initialize PixelDifferenceEncode filter. */
58
static int
59
s_PDiffE_init(stream_state * st)
60
15
{
61
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
62
15
    int bits_per_row = ss->Colors * ss->BitsPerComponent;
63
15
    static const byte cb_values[] = {
64
15
        0, cBits1, cBits2, 0, cBits4, 0, 0, 0, cBits8,
65
15
        0, 0, 0, 0, 0, 0, 0, cBits16
66
15
    };
67
68
15
    if (ss->Colors > s_PDiff_max_Colors)
69
0
        return_error(gs_error_rangecheck);
70
71
15
    if (ss->BitsPerComponent > s_PDiff_max_BPC)
72
0
        return_error(gs_error_rangecheck);
73
74
    /* We know that bits_per_row is initially ss->Colors * ss->BitsPerComponent, and
75
     * we know that can't overflow, because we check the maximum values above. So the
76
     * maximum is currently 960, 16 * 60.
77
     */
78
15
    if (check_int_multiply(bits_per_row, ss->Columns, &bits_per_row) != 0)
79
0
        return_error(gs_error_rangecheck);
80
81
15
    ss->row_count = (bits_per_row + 7) >> 3;
82
15
    ss->end_mask = (1 << (-bits_per_row & 7)) - 1;
83
15
    ss->case_index =
84
15
        cb_values[ss->BitsPerComponent] +
85
15
        (ss->Colors > 4 ? 0 : ss->Colors) + cEncode;
86
15
    return s_PDiff_reinit(st);
87
15
}
88
89
/* Initialize PixelDifferenceDecode filter. */
90
static int
91
s_PDiffD_init(stream_state * st)
92
15
{
93
15
    int code = 0;
94
15
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
95
96
15
    code = s_PDiffE_init(st);
97
15
    ss->case_index += cDecode - cEncode;
98
15
    return code;
99
15
}
100
101
/* Process a buffer.  Note that this handles both Encode and Decode. */
102
static int
103
s_PDiff_process(stream_state * st, stream_cursor_read * pr,
104
                stream_cursor_write * pw, bool last)
105
51
{
106
51
    stream_PDiff_state *const ss = (stream_PDiff_state *) st;
107
51
    const byte *p = pr->ptr;
108
51
    byte *q = pw->ptr;
109
51
    int count;
110
51
    int status = 0;
111
51
    uint s0 = ss->prev[0];
112
51
    byte t = 0;     /* avoid spurious compiler warnings */
113
51
    int  ti;
114
51
    const byte end_mask = ss->end_mask;
115
51
    int colors = ss->Colors;
116
51
    int nb = (colors * ss->BitsPerComponent) >> 3;
117
51
    int final;
118
51
    int ndone, ci;
119
120
15.2k
row:
121
15.2k
    if (ss->row_left == 0) {
122
15.2k
        ss->row_left = ss->row_count;
123
15.2k
        s0 = 0;
124
15.2k
        memset(&ss->prev[1], 0, sizeof(uint) * (s_PDiff_max_Colors - 1));
125
15.2k
    }
126
15.2k
    {
127
15.2k
        int rcount = pr->limit - p;
128
15.2k
        int wcount = pw->limit - q;
129
130
15.2k
        if (ss->row_left < rcount)
131
15.2k
            rcount = ss->row_left;
132
15.2k
        count = (wcount < rcount ? (status = 1, wcount) : rcount);
133
15.2k
    }
134
15.2k
    final = (last && !status ? 1 : nb);
135
15.2k
    ss->row_left -= count;
136
137
    /*
138
     * Encoding and decoding are fundamentally different.
139
     * Encoding computes E[i] = D[i] - D[i-1];
140
     * decoding computes D[i] = E[i] + D[i-1].
141
     * Nevertheless, the loop structures are similar enough that
142
     * we put the code for both functions in the same place.
143
     *
144
     * We only optimize Colors = 1, 3, and 4, which correspond to the common
145
     * color spaces.  (In some cases, it's still simpler to provide a
146
     * separate loop for Colors = 2.)
147
     */
148
149
15.2k
#define LOOP_BY(n, body)\
150
31.4k
  for (; count >= n; count -= n) p += n, q += n, body
151
152
15.2k
    switch (ss->case_index) {
153
154
            /* 1 bit per component */
155
156
0
#define ENCODE1_LOOP(ee)\
157
0
  LOOP_BY(1, (t = *p, *q = ee, s0 = t)); break
158
159
0
#define ENCODE_ALIGNED_LOOP(ee)\
160
0
  BEGIN\
161
0
    ss->prev[0] = s0;\
162
0
    for (; count >= final; count -= ndone) {\
163
0
        ndone = min(count, nb);\
164
0
        for (ci = 0; ci < ndone; ++ci)\
165
0
            t = *++p, *++q = ee, ss->prev[ci] = t;\
166
0
    }\
167
0
    s0 = ss->prev[0];\
168
0
  END
169
170
0
#define ENCODE_UNALIGNED_LOOP(shift, cshift, de)\
171
0
  BEGIN\
172
0
    for (; count >= final; count -= ndone) {\
173
0
        ndone = min(count, nb);\
174
0
        for (ci = 1; ci <= ndone; ++ci) {\
175
0
            ++p;\
176
0
            t = (s0 << (cshift)) | (ss->prev[ci] >> (shift));\
177
0
            *++q = de;\
178
0
            s0 = ss->prev[ci];\
179
0
            ss->prev[ci] = *p;\
180
0
        }\
181
0
    }\
182
0
  END
183
184
0
        case cEncode + cBits1 + 0:
185
0
        case cEncode + cBits1 + 2:
186
0
            if (colors < 8) { /* 2,5,6,7 */
187
0
                int cshift = 8 - colors;
188
189
0
                ENCODE1_LOOP(t ^ ((s0 << cshift) | (t >> colors)));
190
0
            } else if (colors & 7) {
191
0
                int shift = colors & 7;
192
0
                int cshift = 8 - shift;
193
194
0
                ENCODE_UNALIGNED_LOOP(shift, cshift, *p ^ t);
195
0
            } else {
196
0
                ENCODE_ALIGNED_LOOP(t ^ ss->prev[ci]);
197
0
            }
198
0
            break;
199
200
0
        case cEncode + cBits1 + 1:
201
0
            ENCODE1_LOOP(t ^ ((s0 << 7) | (t >> 1)));
202
0
        case cEncode + cBits1 + 3:
203
0
            ENCODE1_LOOP(t ^ ((s0 << 5) | (t >> 3)));
204
0
        case cEncode + cBits1 + 4:
205
0
            ENCODE1_LOOP(t ^ ((s0 << 4) | (t >> 4)));
206
207
0
#define DECODE1_LOOP(te, de)\
208
0
  LOOP_BY(1, (t = te, s0 = *q = de)); break
209
210
0
#define DECODE_ALIGNED_LOOP(de)\
211
0
  BEGIN\
212
0
    ss->prev[0] = s0;\
213
0
    for (; count >= final; count -= ndone) {\
214
0
        ndone = min(count, nb);\
215
0
        for (ci = 0; ci < ndone; ++ci)\
216
0
            t = *++p, ss->prev[ci] = *++q = de;\
217
0
    }\
218
0
    s0 = ss->prev[0];\
219
0
  END
220
221
0
#define DECODE_UNALIGNED_LOOP(shift, cshift, de)\
222
0
  BEGIN\
223
0
    for (; count >= final; count -= ndone) {\
224
0
        ndone = min(count, nb);\
225
0
        for (ci = 1; ci <= ndone; ++ci) {\
226
0
            ++p, ++q;\
227
0
            t = (s0 << (cshift)) | (ss->prev[ci] >> (shift));\
228
0
            s0 = ss->prev[ci];\
229
0
            ss->prev[ci] = *q = de;\
230
0
        }\
231
0
    }\
232
0
  END
233
234
0
        case cDecode + cBits1 + 0:
235
0
            if (colors < 8) { /* 5,6,7 */
236
0
                int cshift = 8 - colors;
237
238
0
                DECODE1_LOOP(*p ^ (s0 << cshift), t ^ (t >> colors));
239
0
            } else if (colors & 7) {
240
0
                int shift = colors & 7;
241
0
                int cshift = 8 - shift;
242
243
0
                DECODE_UNALIGNED_LOOP(shift, cshift, *p ^ t);
244
0
            } else {
245
0
                DECODE_ALIGNED_LOOP(t ^ ss->prev[ci]);
246
0
            }
247
0
            break;
248
249
0
        case cDecode + cBits1 + 1:
250
0
            DECODE1_LOOP(*p ^ (s0 << 7),
251
0
                         (t ^= t >> 1, t ^= t >> 2, t ^ (t >> 4)));
252
0
        case cDecode + cBits1 + 2:
253
0
            DECODE1_LOOP(*p ^ (s0 << 6),
254
0
                         (t ^= (t >> 2), t ^ (t >> 4)));
255
0
        case cDecode + cBits1 + 3:
256
0
            DECODE1_LOOP(*p ^ (s0 << 5),
257
0
                         t ^ (t >> 3) ^ (t >> 6));
258
0
        case cDecode + cBits1 + 4:
259
0
            DECODE1_LOOP(*p ^ (s0 << 4),
260
0
                         t ^ (t >> 4));
261
262
            /* 2 bits per component */
263
264
0
#define ADD4X2(a, b) ( (((a) & (b) & 0x55) << 1) ^ (a) ^ (b) )
265
/* The following computation looks very implausible, but it is correct. */
266
0
#define SUB4X2(a, b) ( ((~(a) & (b) & 0x55) << 1) ^ (a) ^ (b) )
267
268
0
        case cEncode + cBits2 + 0:
269
0
            if (colors & 7) {
270
0
                int shift = (colors & 3) << 1;
271
0
                int cshift = 8 - shift;
272
273
0
                ENCODE_UNALIGNED_LOOP(shift, cshift, SUB4X2(*p, t));
274
0
            } else {
275
0
                ENCODE_ALIGNED_LOOP(SUB4X2(t, ss->prev[ci]));
276
0
            }
277
0
            break;
278
279
0
        case cEncode + cBits2 + 1:
280
0
            ENCODE1_LOOP((s0 = (s0 << 6) | (t >> 2), SUB4X2(t, s0)));
281
0
        case cEncode + cBits2 + 2:
282
0
            ENCODE1_LOOP((s0 = (s0 << 4) | (t >> 4), SUB4X2(t, s0)));
283
0
        case cEncode + cBits2 + 3:
284
0
            ENCODE1_LOOP((s0 = (s0 << 2) | (t >> 6), SUB4X2(t, s0)));
285
0
        case cEncode + cBits2 + 4:
286
0
            ENCODE1_LOOP(SUB4X2(t, s0));
287
288
0
        case cDecode + cBits2 + 0:
289
0
            if (colors & 7) {
290
0
                int shift = (colors & 3) << 1;
291
0
                int cshift = 8 - shift;
292
293
0
                DECODE_UNALIGNED_LOOP(shift, cshift, ADD4X2(*p, t));
294
0
            } else {
295
0
                DECODE_ALIGNED_LOOP(ADD4X2(t, ss->prev[ci]));
296
0
            }
297
0
            break;
298
299
0
        case cDecode + cBits2 + 1:
300
0
            DECODE1_LOOP(*p + (s0 << 6),
301
0
                         (t = ADD4X2(t >> 2, t), ADD4X2(t >> 4, t)));
302
0
        case cDecode + cBits2 + 2:
303
0
            DECODE1_LOOP(*p, (t = ADD4X2(t, s0 << 4), ADD4X2(t >> 4, t)));
304
0
        case cDecode + cBits2 + 3:
305
0
            DECODE1_LOOP(*p, (t = ADD4X2(t, s0 << 2), ADD4X2(t >> 6, t)));
306
0
        case cDecode + cBits2 + 4:
307
0
            DECODE1_LOOP(*p, ADD4X2(t, s0));
308
309
0
#undef ADD4X2
310
0
#undef SUB4X2
311
312
            /* 4 bits per component */
313
314
0
#define ADD2X4(a, b) ( (((a) + (b)) & 0xf) + ((a) & 0xf0) + ((b) & 0xf0) )
315
0
#define ADD2X4R4(a) ( (((a) + ((a) >> 4)) & 0xf) + ((a) & 0xf0) )
316
0
#define SUB2X4(a, b) ( (((a) - (b)) & 0xf) + ((a) & 0xf0) - ((b) & 0xf0) )
317
0
#define SUB2X4R4(a) ( (((a) - ((a) >> 4)) & 0xf) + ((a) & 0xf0) )
318
319
0
        case cEncode + cBits4 + 0:
320
0
        case cEncode + cBits4 + 2:
321
0
    enc4:
322
0
            if (colors & 1) {
323
0
                ENCODE_UNALIGNED_LOOP(4, 4, SUB2X4(*p, t));
324
0
            } else {
325
0
                ENCODE_ALIGNED_LOOP(SUB2X4(t, ss->prev[ci]));
326
0
            }
327
0
            break;
328
329
0
        case cEncode + cBits4 + 1:
330
0
            ENCODE1_LOOP(((t - (s0 << 4)) & 0xf0) | ((t - (t >> 4)) & 0xf));
331
332
0
        case cEncode + cBits4 + 3: {
333
0
            uint s1 = ss->prev[1];
334
335
0
            LOOP_BY(1,
336
0
                    (t = *p,
337
0
                     *q = ((t - (s0 << 4)) & 0xf0) | ((t - (s1 >> 4)) & 0xf),
338
0
                     s0 = s1, s1 = t));
339
0
            ss->prev[1] = s1;
340
0
        } break;
341
342
0
        case cEncode + cBits4 + 4: {
343
0
            uint s1 = ss->prev[1];
344
345
0
            LOOP_BY(2,
346
0
                    (t = p[-1], q[-1] = SUB2X4(t, s0), s0 = t,
347
0
                     t = *p, *q = SUB2X4(t, s1), s1 = t));
348
0
            ss->prev[1] = s1;
349
0
            goto enc4;    /* handle leftover bytes */
350
0
        }
351
352
0
        case cDecode + cBits4 + 0:
353
0
        case cDecode + cBits4 + 2:
354
0
    dec4:
355
0
            if (colors & 1) {
356
0
                DECODE_UNALIGNED_LOOP(4, 4, ADD2X4(*p, t));
357
0
            } else {
358
0
                DECODE_ALIGNED_LOOP(ADD2X4(t, ss->prev[ci]));
359
0
            }
360
0
            break;
361
362
0
        case cDecode + cBits4 + 1:
363
0
            DECODE1_LOOP(*p + (s0 << 4), ADD2X4R4(t));
364
365
0
        case cDecode + cBits4 + 3: {
366
0
            uint s1 = ss->prev[1];
367
368
0
            LOOP_BY(1, (t = (s0 << 4) + (s1 >> 4),
369
0
                        s0 = s1, s1 = *q = ADD2X4(*p, t)));
370
0
            ss->prev[1] = s1;
371
0
        } break;
372
373
0
        case cDecode + cBits4 + 4: {
374
0
            uint s1 = ss->prev[1];
375
376
0
            LOOP_BY(2,
377
0
                    (t = p[-1], s0 = q[-1] = ADD2X4(s0, t),
378
0
                     t = *p, s1 = *q = ADD2X4(s1, t)));
379
0
            ss->prev[1] = s1;
380
0
            goto dec4;    /* handle leftover bytes */
381
0
        }
382
383
0
#undef ADD2X4
384
0
#undef ADD2X4R4
385
0
#undef SUB2X4
386
0
#undef SUB2X4R4
387
388
            /* 8 bits per component */
389
390
0
#define ENCODE8(s, d) (q[d] = p[d] - s, s = p[d])
391
0
#define DECODE8(s, d) q[d] = s += p[d]
392
393
0
        case cEncode + cBits8 + 0:
394
0
        case cEncode + cBits8 + 2:
395
0
            ss->prev[0] = s0;
396
0
            for (; count >= colors; count -= colors)
397
0
                for (ci = 0; ci < colors; ++ci) {
398
0
                    *++q = *++p - ss->prev[ci];
399
0
                    ss->prev[ci] = *p;
400
0
                }
401
0
            s0 = ss->prev[0];
402
0
    enc8:   /* Handle leftover bytes. */
403
0
            if (last && !status)
404
0
                for (ci = 0; ci < count; ++ci)
405
0
                    *++q = *++p - ss->prev[ci],
406
0
                        ss->prev[ci] = *p;
407
0
            break;
408
409
0
        case cDecode + cBits8 + 0:
410
0
        case cDecode + cBits8 + 2:
411
0
            ss->prev[0] = s0;
412
0
            for (; count >= colors; count -= colors)
413
0
                for (ci = 0; ci < colors; ++ci)
414
0
                    *++q = ss->prev[ci] += *++p;
415
0
            s0 = ss->prev[0];
416
0
    dec8:   /* Handle leftover bytes. */
417
0
            if (last && !status)
418
0
                for (ci = 0; ci < count; ++ci)
419
0
                    *++q = ss->prev[ci] += *++p;
420
0
            break;
421
422
0
        case cEncode + cBits8 + 1:
423
0
            LOOP_BY(1, ENCODE8(s0, 0));
424
0
            break;
425
426
15.2k
        case cDecode + cBits8 + 1:
427
15.2k
            LOOP_BY(1, DECODE8(s0, 0));
428
15.2k
            break;
429
430
0
        case cEncode + cBits8 + 3: {
431
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
432
433
0
            LOOP_BY(3, (ENCODE8(s0, -2), ENCODE8(s1, -1),
434
0
                        ENCODE8(s2, 0)));
435
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
436
0
            goto enc8;
437
0
        }
438
439
0
        case cDecode + cBits8 + 3: {
440
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
441
442
0
            LOOP_BY(3, (DECODE8(s0, -2), DECODE8(s1, -1),
443
0
                        DECODE8(s2, 0)));
444
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
445
0
            goto dec8;
446
0
        } break;
447
448
0
        case cEncode + cBits8 + 4: {
449
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
450
451
0
            LOOP_BY(4, (ENCODE8(s0, -3), ENCODE8(s1, -2),
452
0
                        ENCODE8(s2, -1), ENCODE8(s3, 0)));
453
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
454
0
            goto enc8;
455
0
        } break;
456
457
0
        case cDecode + cBits8 + 4: {
458
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
459
460
0
            LOOP_BY(4, (DECODE8(s0, -3), DECODE8(s1, -2),
461
0
                        DECODE8(s2, -1), DECODE8(s3, 0)));
462
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
463
0
            goto dec8;
464
0
        } break;
465
466
0
#undef ENCODE8
467
0
#undef DECODE8
468
469
            /* 16 bits per component */
470
471
0
#define ENCODE16(s, d) (ti = ((p[d-1] << 8) + p[d]), s = ti - s,\
472
0
            q[d-1] = s >> 8, q[d] = s & 0xff, s = ti)
473
0
#define DECODE16(s, d) (s = 0xffff & (s + ((p[d-1] << 8) + p[d])), \
474
0
            q[d-1] = s >> 8, q[d] = s & 0xff)
475
476
0
        case cEncode + cBits16 + 0:
477
0
        case cEncode + cBits16 + 2:
478
0
            ss->prev[0] = s0;
479
0
            for (; count >= colors*2; count -= colors*2)
480
0
                for (ci = 0; ci < colors; ++ci) {
481
0
                    uint k;
482
0
                    ti =  (int)*++p << 8;
483
0
                    ti += (int)*++p;
484
0
                    k = ti - ss->prev[ci];
485
0
                    *++q = k >> 8;
486
0
                    *++q = k & 0xff;
487
0
                    ss->prev[ci] = ti;
488
0
                }
489
0
            s0 = ss->prev[0];
490
0
    enc16:   /* Handle leftover bytes. */
491
0
            if (last && !status)
492
0
                for (ci = 0; ci < count; ++ci)
493
0
                    *++q = *++p - ss->prev[ci],
494
0
                        ss->prev[ci] = *p;
495
0
            break;
496
497
0
        case cDecode + cBits16 + 0:
498
0
        case cDecode + cBits16 + 2:
499
0
            ss->prev[0] = s0;
500
0
            for (; count >= colors*2; count -= colors*2)
501
0
                for (ci = 0; ci < colors; ++ci) {
502
0
                    ti = (int)*++p << 8;
503
0
                    ss->prev[ci] += ti + *++p;
504
0
                    *++q = ss->prev[ci] >> 8;
505
0
                    *++q = ss->prev[ci] & 0xff;
506
0
                }
507
0
            s0 = ss->prev[0];
508
0
    dec16:   /* Ignore leftover bytes. */
509
0
            break;
510
511
0
        case cEncode + cBits16 + 1:
512
0
           LOOP_BY(2, ENCODE16(s0, 0));
513
0
           break;
514
515
0
        case cDecode + cBits16 + 1:
516
0
           LOOP_BY(2, DECODE16(s0, 0));
517
0
           break;
518
519
0
        case cEncode + cBits16 + 3: {
520
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
521
522
0
            LOOP_BY(6, (ENCODE16(s0, -4), ENCODE16(s1, -2),
523
0
                        ENCODE16(s2, 0)));
524
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
525
0
            goto enc16;
526
0
        }
527
528
0
        case cDecode + cBits16 + 3: {
529
0
            uint s1 = ss->prev[1], s2 = ss->prev[2];
530
531
0
            LOOP_BY(6, (DECODE16(s0, -4), DECODE16(s1, -2),
532
0
                        DECODE16(s2, 0)));
533
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2;
534
0
            goto dec16;
535
0
        } break;
536
537
0
        case cEncode + cBits16 + 4: {
538
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
539
540
0
            LOOP_BY(8, (ENCODE16(s0, -6), ENCODE16(s1, -4),
541
0
                        ENCODE16(s2, -2), ENCODE16(s3, 0)));
542
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
543
0
            goto enc16;
544
0
        } break;
545
546
0
        case cDecode + cBits16 + 4: {
547
0
            uint s1 = ss->prev[1], s2 = ss->prev[2], s3 = ss->prev[3];
548
549
0
            LOOP_BY(8, (DECODE16(s0, -6), DECODE16(s1, -4),
550
0
                        DECODE16(s2, -2), DECODE16(s3, 0)));
551
0
            ss->prev[0] = s0, ss->prev[1] = s1, ss->prev[2] = s2, ss->prev[3] = s3;
552
0
            goto dec16;
553
0
        } break;
554
555
15.2k
#undef ENCODE16
556
15.2k
#undef DECODE16
557
558
15.2k
    }
559
15.2k
#undef LOOP_BY
560
15.2k
#undef ENCODE1_LOOP
561
15.2k
#undef DECODE1_LOOP
562
15.2k
    ss->row_left += count;  /* leftover bytes are possible */
563
15.2k
    if (ss->row_left == 0) {
564
15.2k
        if (end_mask != 0)
565
0
            *q = (*q & ~end_mask) | (*p & end_mask);
566
15.2k
        if (p < pr->limit && q < pw->limit)
567
15.2k
            goto row;
568
15.2k
    }
569
51
    ss->prev[0] = s0;
570
51
    pr->ptr = p;
571
51
    pw->ptr = q;
572
51
    return status;
573
15.2k
}
574
575
/* Stream templates */
576
const stream_template s_PDiffE_template = {
577
    &st_PDiff_state, s_PDiffE_init, s_PDiff_process, 1, 1, NULL,
578
    s_PDiff_set_defaults, s_PDiff_reinit
579
};
580
const stream_template s_PDiffD_template = {
581
    &st_PDiff_state, s_PDiffD_init, s_PDiff_process, 1, 1, NULL,
582
    s_PDiff_set_defaults, s_PDiff_reinit
583
};