Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/base/gxclutil.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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
/* Command list writing utilities. */
18
19
#include "memory_.h"
20
#include "string_.h"
21
#include "gx.h"
22
#include "gp.h"
23
#include "gpcheck.h"
24
#include "gserrors.h"
25
#include "gxdevice.h"
26
#include "gxdevmem.h"   /* must precede gxcldev.h */
27
#include "gxcldev.h"
28
#include "gxclpath.h"
29
#include "gsparams.h"
30
31
#include "valgrind.h"
32
33
/* ---------------- Statistics ---------------- */
34
35
#ifdef DEBUG
36
const char *const cmd_op_names[16] =
37
{cmd_op_name_strings};
38
static const char *const cmd_misc_op_names[16] =
39
{cmd_misc_op_name_strings};
40
static const char *const cmd_misc2_op_names[16] =
41
{cmd_misc2_op_name_strings};
42
static const char *const cmd_segment_op_names[16] =
43
{cmd_segment_op_name_strings};
44
static const char *const cmd_path_op_names[16] =
45
{cmd_path_op_name_strings};
46
const char *const *const cmd_sub_op_names[16] =
47
{cmd_misc_op_names, 0, 0, 0, 0, 0, 0, 0,
48
 0, 0, 0, 0,
49
 0, cmd_misc2_op_names, cmd_segment_op_names, cmd_path_op_names
50
};
51
const char *cmd_extend_op_names[256] =
52
{cmd_extend_op_name_strings};
53
54
#ifdef COLLECT_STATS_CLIST
55
struct stats_cmd_s {
56
    ulong op_counts[512];
57
    ulong op_sizes[512];
58
    ulong tile_reset, tile_found, tile_added;
59
    ulong same_band, other_band;
60
} stats_cmd;
61
extern ulong stats_cmd_diffs[5];  /* in gxclpath.c */
62
int
63
cmd_count_op(int op, uint size,const gs_memory_t *mem)
64
{
65
    stats_cmd.op_counts[op]++;
66
    stats_cmd.op_sizes[op] += size;
67
    if (gs_debug_c('L')) {
68
        const char *const *sub = cmd_sub_op_names[op >> 4];
69
70
        if (sub)
71
            dmlprintf2(mem, ", %s(%u)\n", sub[op & 0xf], size);
72
        else
73
            dmlprintf3(mem, ", %s %d(%u)\n", cmd_op_names[op >> 4], op & 0xf,
74
                      size);
75
        dmflush(mem);
76
    }
77
    return op;
78
}
79
int
80
cmd_count_extended_op(int op, uint size,const gs_memory_t *mem)
81
{
82
    stats_cmd.op_counts[cmd_opv_extend]++;
83
    stats_cmd.op_sizes[cmd_opv_extend] += size;
84
    stats_cmd.op_counts[256+op]++;
85
    stats_cmd.op_sizes[256+op] += size;
86
    if (gs_debug_c('L')) {
87
        const char *ext = cmd_extend_op_names[op];
88
89
        if (ext)
90
            dmlprintf2(mem, ", %s(%u)\n", ext, size);
91
        else
92
            dmlprintf2(mem, ", ?0x%02x?(%u)\n", op,
93
                      size);
94
        dmflush(mem);
95
    }
96
    return op;
97
}
98
void
99
cmd_uncount_op(int op, uint size)
100
{
101
    stats_cmd.op_counts[op]--;
102
    stats_cmd.op_sizes[op] -= size;
103
}
104
#endif
105
#endif
106
107
/* Print statistics. */
108
#ifdef COLLECT_STATS_CLIST
109
void
110
cmd_print_stats(const gs_memory_t *mem)
111
{
112
    int ci, cj;
113
114
    dmlprintf3(mem, "[l]counts: reset = %lu, found = %lu, added = %lu\n",
115
              stats_cmd.tile_reset, stats_cmd.tile_found,
116
              stats_cmd.tile_added);
117
    dmlprintf5(mem, "     diff 2.5 = %lu, 3 = %lu, 4 = %lu, 2 = %lu, >4 = %lu\n",
118
              stats_cmd_diffs[0], stats_cmd_diffs[1], stats_cmd_diffs[2],
119
              stats_cmd_diffs[3], stats_cmd_diffs[4]);
120
    dmlprintf2(mem, "     same_band = %lu, other_band = %lu\n",
121
              stats_cmd.same_band, stats_cmd.other_band);
122
    for (ci = 0; ci < 0x100; ci += 0x10) {
123
        const char *const *sub = cmd_sub_op_names[ci >> 4];
124
125
        if (sub != 0) {
126
            dmlprintf1(mem, "[l]  %s =", cmd_op_names[ci >> 4]);
127
            for (cj = ci; cj < ci + 0x10; cj += 2)
128
                dmprintf6(mem, "\n\t%s = %lu(%lu), %s = %lu(%lu)",
129
                         sub[cj - ci],
130
                         stats_cmd.op_counts[cj], stats_cmd.op_sizes[cj],
131
                         sub[cj - ci + 1],
132
                   stats_cmd.op_counts[cj + 1], stats_cmd.op_sizes[cj + 1]);
133
        } else {
134
            ulong tcounts = 0, tsizes = 0;
135
136
            for (cj = ci; cj < ci + 0x10; cj++)
137
                tcounts += stats_cmd.op_counts[cj],
138
                    tsizes += stats_cmd.op_sizes[cj];
139
            dmlprintf3(mem, "[l]  %s (%lu,%lu) =\n\t",
140
                      cmd_op_names[ci >> 4], tcounts, tsizes);
141
            for (cj = ci; cj < ci + 0x10; cj++)
142
                if (stats_cmd.op_counts[cj] == 0)
143
                    dmputs(mem, " -");
144
                else
145
                    dmprintf2(mem, " %lu(%lu)", stats_cmd.op_counts[cj],
146
                             stats_cmd.op_sizes[cj]);
147
        }
148
        dmputs(mem, "\n");
149
    }
150
    for (ci = 0x100; ci < 0x200; ci ++) {
151
        const char *ext = cmd_extend_op_names[ci-0x100];
152
153
        if (ext != NULL) {
154
            dmprintf3(mem, "[l] %s (%lu,%lu)\n",
155
                         ext,
156
                         stats_cmd.op_counts[ci], stats_cmd.op_sizes[ci]);
157
        } else if (stats_cmd.op_counts[ci] || stats_cmd.op_sizes[ci]) {
158
            dmprintf3(mem, "[l] ?0x%02x? (%lu,%lu)\n",
159
                      ci-0x100,
160
                      stats_cmd.op_counts[ci], stats_cmd.op_sizes[ci]);
161
        }
162
        dmputs(mem, "\n");
163
    }
164
}
165
#endif /* DEBUG */
166
167
/* ---------------- Writing utilities ---------------- */
168
169
/* Update the 'trans_bbox' in the states for bands affected by the given rectangle */
170
/* The caller has determined the the PDF 1.4 transparency will actuall be needed   */
171
/* for the given rectangle (conservatively). This will allow some bands that only  */
172
/* paint to the page level with full opacity to skip the pdf14 compositor during   */
173
/* rendering/reading and thus run faster and with less memory for those bands.     */
174
void
175
clist_update_trans_bbox(gx_device_clist_writer *cldev, gs_int_rect *bbox)
176
4.46M
{
177
4.46M
    int p_y, q_y;
178
4.46M
    int band, first_band, last_band;
179
180
4.46M
    first_band = max(0, bbox->p.y / cldev->page_band_height);
181
4.46M
    p_y = bbox->p.y - (first_band * cldev->page_band_height);
182
4.46M
    last_band = min((cldev->nbands - 1), bbox->q.y / cldev->page_band_height);
183
184
11.8M
    for (band=first_band; band <= last_band; band++) {
185
7.39M
        if (cldev->states[band].color_usage.trans_bbox.p.y > p_y)
186
46.2k
            cldev->states[band].color_usage.trans_bbox.p.y = p_y;
187
7.39M
        if (cldev->states[band].color_usage.trans_bbox.p.x > bbox->p.x)
188
54.1k
            cldev->states[band].color_usage.trans_bbox.p.x = bbox->p.x;
189
7.39M
        p_y = 0;  /* will be top of next band */
190
7.39M
        q_y = (band == last_band) ? bbox->q.y - (last_band * cldev->page_band_height) :
191
7.39M
                                      cldev->page_band_height - 1;
192
7.39M
        if (cldev->states[band].color_usage.trans_bbox.q.y < q_y)
193
58.4k
            cldev->states[band].color_usage.trans_bbox.q.y = q_y;
194
7.39M
        if (cldev->states[band].color_usage.trans_bbox.q.x < bbox->q.x)
195
885k
            cldev->states[band].color_usage.trans_bbox.q.x = bbox->q.x;
196
7.39M
    }
197
4.46M
}
198
199
/* Write the commands for one band or band range. */
200
static int  /* ret 0 all ok, -ve error code, or +1 ok w/low-mem warning */
201
cmd_write_band(gx_device_clist_writer * cldev, int band_min, int band_max,
202
               cmd_list * pcl, byte cmd_end)
203
3.85M
{
204
3.85M
    const cmd_prefix *cp = pcl->head;
205
3.85M
    int code_b = 0;
206
3.85M
    int code_c = 0;
207
208
3.85M
    if (cp != 0 || cmd_end != cmd_opv_end_run) {
209
720k
        clist_file_ptr cfile = cldev->page_cfile;
210
720k
        clist_file_ptr bfile = cldev->page_bfile;
211
720k
        cmd_block cb;
212
720k
        byte end;
213
214
720k
        if (cfile == 0 || bfile == 0)
215
0
            return_error(gs_error_ioerror);
216
720k
        cb.band_min = band_min;
217
720k
        cb.band_max = band_max;
218
720k
        cb.pos = cldev->page_info.io_procs->ftell(cfile);
219
720k
        if_debug3m('l', cldev->memory, "[l]writing for bands (%d,%d) at %"PRId64"\n",
220
720k
                  band_min, band_max, cb.pos);
221
720k
        cldev->page_info.io_procs->fwrite_chars(&cb, sizeof(cb), bfile);
222
720k
        if (cp != 0) {
223
481k
            pcl->tail->next = 0;  /* terminate the list */
224
2.88M
            for (; cp != 0; cp = cp->next) {
225
#ifdef DEBUG
226
                if ((const byte *)cp < cldev->cbuf ||
227
                    (const byte *)cp >= cldev->cend ||
228
                    cp->size > cldev->cend - (const byte *)cp
229
                    ) {
230
                    mlprintf1(cldev->memory, "cmd_write_band error at "PRI_INTPTR"\n", (intptr_t) cp);
231
                    return_error(gs_error_Fatal);
232
                }
233
#endif
234
2.40M
                if_debug2m('L', cldev->memory, "[L] cmd id=%ld at %"PRId64"\n",
235
2.40M
                           cp->id, cldev->page_info.io_procs->ftell(cfile));
236
2.40M
                cldev->page_info.io_procs->fwrite_chars(cp + 1, cp->size, cfile);
237
2.40M
            }
238
481k
            pcl->head = pcl->tail = 0;
239
481k
        }
240
720k
        if_debug0m('L', cldev->memory, "[L] adding terminator\n");
241
720k
        end  = cmd_count_op(cmd_end, 1, cldev->memory);
242
720k
        cldev->page_info.io_procs->fwrite_chars(&end, 1, cfile);
243
720k
        process_interrupts(cldev->memory);
244
720k
        code_b = cldev->page_info.io_procs->ferror_code(bfile);
245
720k
        code_c = cldev->page_info.io_procs->ferror_code(cfile);
246
720k
        if (code_b < 0)
247
0
            return_error(code_b);
248
720k
        if (code_c < 0)
249
7
            return_error(code_c);
250
720k
    }
251
3.85M
    return code_b | code_c;
252
3.85M
}
253
254
/* Write out a pseudo-band block of data, using the specific pseudo_band_offset */
255
int
256
cmd_write_pseudo_band(gx_device_clist_writer * cldev, unsigned char *pbuf, int data_size, int pseudo_band_offset)
257
7.73k
{
258
259
    /* Data is written out maxband + pseudo_band_offset */
260
261
7.73k
    int band = cldev->band_range_max + pseudo_band_offset;
262
7.73k
    clist_file_ptr cfile = cldev->page_cfile;
263
7.73k
    clist_file_ptr bfile = cldev->page_bfile;
264
7.73k
    cmd_block cb;
265
7.73k
    int code_b, code_c;
266
267
7.73k
    if (cfile == 0 || bfile == 0)
268
0
        return_error(gs_error_ioerror);
269
270
    /* Set up the command block information that
271
       is stored in the bfile. */
272
273
7.73k
    cb.band_min = band;
274
7.73k
    cb.band_max = band;
275
7.73k
    cb.pos = cldev->page_info.io_procs->ftell(cfile);
276
277
7.73k
    if_debug2m('l', cldev->memory, "[l]writing pseudo band %d cb pos %"PRId64"\n",
278
7.73k
                  band, cb.pos);
279
280
7.73k
    cldev->page_info.io_procs->fwrite_chars(&cb, sizeof(cb), bfile);
281
282
    /* Now store the information in the cfile */
283
7.73k
    if_debug2m('l', cldev->memory, "[l]writing %d bytes into cfile at %"PRId64"\n",
284
7.73k
            data_size, cldev->page_info.io_procs->ftell(cfile));
285
286
7.73k
    cldev->page_info.io_procs->fwrite_chars(pbuf, data_size, cfile);
287
288
7.73k
    process_interrupts(cldev->memory);
289
7.73k
    code_b = cldev->page_info.io_procs->ferror_code(bfile);
290
7.73k
    code_c = cldev->page_info.io_procs->ferror_code(cfile);
291
292
7.73k
    if (code_b < 0)
293
0
        return_error(code_b);
294
7.73k
    if (code_c < 0)
295
0
        return_error(code_c);
296
297
7.73k
    return code_b | code_c;
298
7.73k
}
299
300
/* Write out the buffered commands, and reset the buffer. */
301
int /* ret 0 all-ok, -ve error code, or +1 ok w/low-mem warning */
302
cmd_write_buffer(gx_device_clist_writer * cldev, byte cmd_end)
303
25.9k
{
304
25.9k
    int nbands = cldev->nbands;
305
25.9k
    gx_clist_state *pcls;
306
25.9k
    int band;
307
25.9k
    int code = cmd_write_band(cldev, cldev->band_range_min,
308
25.9k
                              cldev->band_range_max,
309
25.9k
                              cldev->band_range_list,
310
25.9k
                              cmd_opv_end_run);
311
312
25.9k
    int warning = code;
313
314
25.9k
    for (band = 0, pcls = cldev->states;
315
3.85M
         code >= 0 && band < nbands; band++, pcls++
316
3.82M
         ) {
317
3.82M
        code = cmd_write_band(cldev, band, band, &pcls->list, cmd_end);
318
3.82M
        warning |= code;
319
3.82M
    }
320
    /* If an error occurred, finish cleaning up the pointers. */
321
26.7k
    for (; band < nbands; band++, pcls++)
322
865
        pcls->list.head = pcls->list.tail = 0;
323
25.9k
    cldev->cnext = cldev->cbuf;
324
#ifdef HAVE_VALGRIND
325
    VALGRIND_MAKE_MEM_UNDEFINED(cldev->cbuf, cldev->cend - cldev->cbuf);
326
#endif
327
25.9k
    cldev->ccl = 0;
328
#ifdef COLLECT_STATS_CLIST
329
    if (gs_debug_c('l'))
330
        cmd_print_stats(cldev->memory);
331
#endif
332
25.9k
    return_check_interrupt(cldev->memory, code != 0 ? code : warning);
333
25.9k
}
334
335
/*
336
 * Add a command to the appropriate band list, and allocate space for its
337
 * data.  Return the pointer to the data area.  If an error or (low-memory
338
 * warning) occurs, set cldev->error_code and return 0.
339
 */
340
19.4M
#define cmd_headroom (sizeof(cmd_prefix) + ARCH_ALIGN_PTR_MOD)
341
byte *
342
cmd_put_list_op(gx_device_clist_writer * cldev, cmd_list * pcl, uint size)
343
18.6M
{
344
18.6M
    byte *dp = cldev->cnext;
345
346
18.6M
    CMD_CHECK_LAST_OP_BLOCK_DEFINED(cldev);
347
348
18.6M
    if (size + cmd_headroom > cldev->cend - dp) {
349
2.24k
        cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run);
350
        /* error_code can come back as +ve as a warning that memory
351
         * is getting tight. Don't fail on that. */
352
2.24k
        if (cldev->error_code < 0 ||
353
2.24k
            (size + cmd_headroom > cldev->cend - cldev->cnext)) {
354
2
            if (cldev->error_code == 0)
355
0
                cldev->error_code = gs_error_VMerror;
356
2
            return 0;
357
2
        }
358
2.23k
        else
359
2.23k
            return cmd_put_list_op(cldev, pcl, size);
360
2.24k
    }
361
18.6M
    if (cldev->ccl == pcl) { /* We're adding another command for the same band. */
362
        /* Tack it onto the end of the previous one. */
363
16.2M
        cmd_count_add1(stats_cmd.same_band);
364
#ifdef DEBUG
365
        if (pcl->tail->size > dp - (byte *) (pcl->tail + 1)) {
366
            lprintf1("cmd_put_list_op error at "PRI_INTPTR"\n", (intptr_t)pcl->tail);
367
        }
368
#endif
369
16.2M
        if_debug2m('L', cldev->memory, "[L] id:%ld+%ld",
370
16.2M
                   pcl->tail->id, (long)pcl->tail->size);
371
16.2M
        pcl->tail->size += size;
372
16.2M
    } else {
373
        /* Skip to an appropriate alignment boundary. */
374
        /* (We assume the command buffer itself is aligned.) */
375
2.41M
        cmd_prefix *cp = (cmd_prefix *)
376
2.41M
            (dp + ((cldev->cbuf - dp) & (ARCH_ALIGN_PTR_MOD - 1)));
377
378
2.41M
        cp->id = cldev->ins_count++;
379
#ifdef DEBUG
380
        if (gs_debug_c('L'))
381
        {
382
            if (pcl == cldev->band_range_list)
383
                dmlprintf2(cldev->memory, "[L]Change to bands=(%d->%d)", cldev->band_range_min, cldev->band_range_max);
384
            else
385
                dmlprintf1(cldev->memory, "[L]Change to band=%d",
386
                           (int)(((intptr_t)pcl-(intptr_t)&cldev->states->list)/sizeof(*cldev->states)));
387
388
            dmlprintf2(cldev->memory, ", align=%d\n[L] id:%ld+0",
389
                       (int)((char *)cp-(char *)dp), cp->id);
390
        }
391
#endif
392
393
2.41M
        cmd_count_add1(stats_cmd.other_band);
394
2.41M
        dp = (byte *) (cp + 1);
395
2.41M
        if (pcl->tail != 0) {
396
#ifdef DEBUG
397
            if (pcl->tail < pcl->head ||
398
                pcl->tail->size > dp - (byte *) (pcl->tail + 1)
399
                ) {
400
                lprintf1("cmd_put_list_op error at "PRI_INTPTR"\n",
401
                         (intptr_t)pcl->tail);
402
            }
403
#endif
404
1.92M
            pcl->tail->next = cp;
405
1.92M
        } else
406
484k
            pcl->head = cp;
407
2.41M
        pcl->tail = cp;
408
2.41M
        cldev->ccl = pcl;
409
2.41M
        cp->size = size;
410
2.41M
    }
411
18.6M
    cldev->cnext = dp + size;
412
18.6M
    return dp;
413
18.6M
}
414
415
byte *
416
cmd_put_list_extended_op(gx_device_clist_writer *cldev, cmd_list *pcl, int op, uint size)
417
0
{
418
0
    byte *dp = cmd_put_list_op(cldev, pcl, size);
419
420
0
    if (dp) {
421
0
        dp[1] = op;
422
423
0
        if (gs_debug_c('L')) {
424
0
            clist_debug_op(cldev->memory, dp);
425
0
            dmlprintf1(cldev->memory, "[%u]\n", size);
426
0
        }
427
0
    }
428
429
0
    return dp;
430
0
}
431
432
/* Request a space in the buffer.
433
   Writes out the buffer if necessary.
434
   Returns the size of available space. */
435
int
436
cmd_get_buffer_space(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size)
437
406k
{
438
406k
    CMD_CHECK_LAST_OP_BLOCK_DEFINED(cldev);
439
440
406k
    if (size + cmd_headroom > cldev->cend - cldev->cnext) {
441
        /* error_code can come back as +ve as a warning that memory
442
         * is getting tight. Don't fail on that. */
443
205
        cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run);
444
205
        if (cldev->error_code < 0) {
445
0
            return cldev->error_code;
446
0
        }
447
205
    }
448
406k
    return cldev->cend - cldev->cnext - cmd_headroom;
449
406k
}
450
451
#ifdef DEBUG
452
byte *
453
cmd_put_op(gx_device_clist_writer * cldev, gx_clist_state * pcls, uint size)
454
{
455
    return cmd_put_list_op(cldev, &pcls->list, size);
456
}
457
#endif
458
459
/* Add a command for a range of bands. */
460
byte *
461
cmd_put_range_op(gx_device_clist_writer * cldev, int band_min, int band_max,
462
                 uint size)
463
36.3k
{
464
36.3k
    CMD_CHECK_LAST_OP_BLOCK_DEFINED(cldev);
465
466
36.3k
    if (cldev->ccl != 0 &&
467
36.3k
        (cldev->ccl != cldev->band_range_list ||
468
30.5k
         band_min != cldev->band_range_min ||
469
30.5k
         band_max != cldev->band_range_max)
470
36.3k
        ) {
471
16.6k
        cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run);
472
        /* error_code can come back as +ve as a warning that memory
473
         * is getting tight. Don't fail on that. */
474
16.6k
        if (cldev->error_code < 0) {
475
2
            return NULL;
476
2
        }
477
16.6k
        cldev->band_range_min = band_min;
478
16.6k
        cldev->band_range_max = band_max;
479
16.6k
        if_debug2m('L', cldev->memory, "[L]Band range(%d,%d)\n",
480
16.6k
                   band_min, band_max);
481
16.6k
    }
482
36.3k
    return cmd_put_list_op(cldev, cldev->band_range_list, size);
483
36.3k
}
484
485
/* Write a variable-size positive integer. */
486
int
487
cmd_size_w(register uint w)
488
8.19M
{
489
8.19M
    register int size = 1;
490
491
16.5M
    while (w > 0x7f)
492
8.32M
        w >>= 7, size++;
493
8.19M
    return size;
494
8.19M
}
495
byte *
496
cmd_put_w(register uint w, register byte * dp)
497
9.66M
{
498
19.2M
    while (w > 0x7f)
499
9.57M
        *dp++ = w | 0x80, w >>= 7;
500
9.66M
    *dp = w;
501
9.66M
    return dp + 1;
502
9.66M
}
503
/* Write a variable-size positive fractional. */
504
int
505
cmd_size_frac31(register frac31 w)
506
0
{
507
0
    register int size = 1;
508
0
    register uint32_t v = w;
509
510
0
    while (v & 0x01FFFFFF)
511
0
        v <<= 7, size++;
512
0
    return size;
513
0
}
514
byte *
515
cmd_put_frac31(register frac31 w, register byte * dp)
516
0
{
517
0
    register uint32_t v = w;
518
519
0
    while (v & 0x01FFFFFF)
520
0
        *dp++ = (v >> 24) | 1, v <<= 7;
521
0
    *dp = (v >> 24);
522
0
    return dp + 1;
523
0
}
524
525
/*
526
 * This next two arrays are used for the 'delta' mode of placing a color
527
 * in the clist.  These arrays are indexed by the number of bytes in the
528
 * color value (the depth).
529
 *
530
 * Delta values are calculated by subtracting the old value for the color
531
 * from the desired new value.  Then each byte of the differenece is
532
 * examined.  For most bytes, if the difference fits into 4 bits (signed)
533
 * then those bits are packed into the clist along with an opcode.  If
534
 * the size of the color (the depth) is an odd number of bytes then instead
535
 * of four bits per byte, extra bits are used for the upper three bytes
536
 * of the color.  In this case, five bits are used for the first byte,
537
 * six bits for the second byte, and five bits for third byte.  This
538
 * maximizes the chance that the 'delta' mode can be used for placing
539
 * colors in the clist.
540
 */
541
/*
542
 * Depending upon the compiler and user choices, the size of a gx_color_index
543
 * may be 4 to 8 bytes.  We will define table entries for up to 8 bytes.
544
 * This macro is being used to prevent compiler warnings if gx_color_index is
545
 * only 4 bytes.
546
 */
547
#define tab_entry(x) ((x) & (~((gx_color_index) 0)))
548
549
const gx_color_index cmd_delta_offsets[] = {
550
        tab_entry(0),
551
        tab_entry(0),
552
        tab_entry(0x0808),
553
        tab_entry(0x102010),
554
        tab_entry(0x08080808)
555
#if ARCH_SIZEOF_GX_COLOR_INDEX > 4
556
        ,
557
        tab_entry(0x1020100808),
558
        tab_entry(0x080808080808),
559
        tab_entry(0x10201008080808),
560
        tab_entry(0x0808080808080808)
561
#endif
562
        };
563
564
static const gx_color_index cmd_delta_masks[] = {
565
        tab_entry(0),
566
        tab_entry(0),
567
        tab_entry(0x0f0f),
568
        tab_entry(0x1f3f1f),
569
        tab_entry(0x0f0f0f0f)
570
#if ARCH_SIZEOF_GX_COLOR_INDEX > 4
571
        ,
572
        tab_entry(0x1f3f1f0f0f),
573
        tab_entry(0x0f0f0f0f0f0f),
574
        tab_entry(0x1f3f1f0f0f0f0f),
575
        tab_entry(0x0f0f0f0f0f0f0f0f)
576
#endif
577
        };
578
579
#undef tab_entry
580
581
/*
582
 * There are currently only four different color "types" that can be placed
583
 * into the clist.  These are called "color0", "color1", and "tile_color0",
584
 * and "tile_color1".  There are separate command codes for color0 versus
585
 * color1, both for the full value and delta commands - see cmd_put_color.
586
 * Tile colors are preceded by a cmd_opv_set_tile_color command.
587
 */
588
const clist_select_color_t
589
    clist_select_color0 = {cmd_op_set_color0, cmd_opv_delta_color0, 0},
590
    clist_select_color1 = {cmd_op_set_color1, cmd_opv_delta_color1, 0},
591
    clist_select_tile_color0 = {cmd_op_set_color0, cmd_opv_delta_color0, 1},
592
    clist_select_tile_color1 = {cmd_op_set_color1, cmd_opv_delta_color1, 1};
593
594
/*
595
 * This routine is used to place a color into the clist.  Colors, in the
596
 * clist, can be specified either as by a full value or by a "delta" value.
597
 *
598
 * See the comments before cmd_delta_offsets[] for a description of the
599
 * 'delta' mode.  The delta mode may allow for a smaller command in the clist.
600
 *
601
 * For the full value mode, values are sent as a cmd code plus n bytes of
602
 * data.  To minimize the number of bytes, a count is made of any low order
603
 * bytes which are zero.  This count is packed into the low order 4 bits
604
 * of the cmd code.  The data for these bytes are not sent.
605
 *
606
 * The gx_no_color_index value is treated as a special case.  This is done
607
 * because it is both a commonly sent value and because it may require
608
 * more bytes then the other color values.
609
 *
610
 * Parameters:
611
 *   cldev - Pointer to clist device
612
 *   pcls - Pointer to clist state
613
 *   select - Descriptor record for type of color being sent.  See comments
614
 *       by clist_select_color_t.
615
 *   color - The new color value.
616
 *   pcolor - Pointer to previous color value.  (If the color value is the
617
 *       same as the previous value then nothing is placed into the clist.)
618
 *
619
 * Returns:
620
 *   Error code
621
 *   clist and pcls and cldev may be updated.
622
 */
623
int
624
cmd_put_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
625
              const clist_select_color_t * select,
626
              gx_color_index color, gx_color_index * pcolor)
627
2.93M
{
628
2.93M
    byte * dp;    /* This is manipulated by the set_cmd_put_op macro */
629
2.93M
    gx_color_index diff = color - *pcolor;
630
2.93M
    byte op, op_delta;
631
2.93M
    int code;
632
633
2.93M
    if (diff == 0)
634
0
        return 0;
635
636
    /* If this is a tile color then send tile color type */
637
2.93M
    if (select->tile_color) {
638
30.4k
        code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_set_tile_color, 1);
639
30.4k
        if (code < 0)
640
0
            return code;
641
30.4k
    }
642
2.93M
    op = select->set_op;
643
2.93M
    op_delta = select->delta_op;
644
2.93M
    if (color == gx_no_color_index) {
645
        /*
646
         * We must handle this specially, because it may take more
647
         * bytes than the color depth.
648
         */
649
0
        code = set_cmd_put_op(&dp, cldev, pcls, op + cmd_no_color_index, 1);
650
0
        if (code < 0)
651
0
            return code;
652
2.93M
    } else {
653
        /* Check if the "delta" mode command can be used. */
654
        /* clist_color_info may be different than target device due to
655
         * transparency group during clist writing phase */
656
2.93M
        int depth = (cldev->clist_color_info.depth <= sizeof(gx_color_index)*8 ?
657
2.93M
                     cldev->clist_color_info.depth : sizeof(gx_color_index)*8);
658
2.93M
        int num_bytes = (depth + 7) >> 3;
659
2.93M
        int delta_bytes = (num_bytes + 1) / 2;
660
2.93M
        gx_color_index delta_offset = cmd_delta_offsets[num_bytes];
661
2.93M
        gx_color_index delta_mask = cmd_delta_masks[num_bytes];
662
2.93M
        gx_color_index delta = (diff + delta_offset) & delta_mask;
663
2.93M
        bool use_delta = (color == (*pcolor + delta - delta_offset));
664
2.93M
        int bytes_dropped = 0;
665
2.93M
        gx_color_index data = color;
666
667
        /*
668
         * If we use the full value mode, we do not send low order bytes
669
         * which are zero. Determine how many low order bytes are zero.
670
         */
671
2.93M
        if (color == 0) {
672
195k
            bytes_dropped = num_bytes;
673
195k
        }
674
2.73M
        else  {
675
2.76M
            while ((data & 0xff) == 0) {
676
25.0k
                bytes_dropped++;
677
25.0k
                data >>= 8;
678
25.0k
            }
679
2.73M
        }
680
        /* Now send one of the two command forms */
681
2.93M
        if (use_delta && delta_bytes < (num_bytes - bytes_dropped)) {
682
1.26M
            code = set_cmd_put_op(&dp, cldev, pcls,
683
1.26M
                                        op_delta, delta_bytes + 1);
684
1.26M
            if (code < 0)
685
0
                return code;
686
            /*
687
             * If we have an odd number of bytes then use extra bits for
688
             * the high order three bytes of the color.
689
             */
690
1.26M
            if ((num_bytes >= 3) && (num_bytes & 1)) {
691
686k
                data = delta >> ((num_bytes - 3) * 8);
692
686k
                dp[delta_bytes--] = (byte)(((data >> 13) & 0xf8) + ((data >> 11) & 0x07));
693
686k
                dp[delta_bytes--] = (byte)(((data >> 3) & 0xe0) + (data & 0x1f));
694
686k
            }
695
2.42M
            for(; delta_bytes>0; delta_bytes--) {
696
1.15M
                dp[delta_bytes] = (byte)((delta >> 4) + delta);
697
1.15M
                delta >>= 16;
698
1.15M
            }
699
1.26M
        }
700
1.66M
        else {
701
1.66M
            num_bytes -= bytes_dropped;
702
1.66M
            code = set_cmd_put_op(&dp, cldev, pcls,
703
1.66M
                                (byte)(op + bytes_dropped), num_bytes + 1);
704
1.66M
            if (code < 0)
705
0
                return code;
706
4.08M
            for(; num_bytes>0; num_bytes--) {
707
2.42M
                dp[num_bytes] = (byte)data;
708
2.42M
                data >>= 8;
709
2.42M
            }
710
1.66M
        }
711
2.93M
    }
712
2.93M
    *pcolor = color;
713
2.93M
    return 0;
714
2.93M
}
715
716
/* Put out a command to set the tile colors. */
717
int
718
cmd_set_tile_colors(gx_device_clist_writer * cldev, gx_clist_state * pcls,
719
                    gx_color_index color0, gx_color_index color1)
720
16.7k
{
721
16.7k
    int code = 0;
722
723
16.7k
    if (color0 != pcls->tile_colors[0]) {
724
14.5k
        code = cmd_put_color(cldev, pcls,
725
14.5k
                             &clist_select_tile_color0,
726
14.5k
                             color0, &pcls->tile_colors[0]);
727
14.5k
        if (code != 0)
728
0
            return code;
729
14.5k
    }
730
16.7k
    if (color1 != pcls->tile_colors[1])
731
15.8k
        code = cmd_put_color(cldev, pcls,
732
15.8k
                             &clist_select_tile_color1,
733
15.8k
                             color1, &pcls->tile_colors[1]);
734
16.7k
    return code;
735
16.7k
}
736
737
/* Put out a command to set the tile phase. */
738
int
739
cmd_set_tile_phase_generic(gx_device_clist_writer * cldev, gx_clist_state * pcls,
740
                   int px, int py, bool all_bands)
741
0
{
742
0
    int pcsize;
743
0
    byte *dp;
744
0
    int code;
745
746
0
    pcsize = 1 + cmd_size2w(px, py);
747
0
    if (all_bands)
748
0
        code = set_cmd_put_all_op(&dp, cldev, (byte)cmd_opv_set_tile_phase, pcsize);
749
0
    else
750
0
        code = set_cmd_put_op(&dp, cldev, pcls, (byte)cmd_opv_set_tile_phase, pcsize);
751
0
    if (code < 0)
752
0
        return code;
753
0
    ++dp;
754
0
    pcls->tile_phase.x = px;
755
0
    pcls->tile_phase.y = py;
756
0
    cmd_putxy(pcls->tile_phase, &dp);
757
0
    return 0;
758
0
}
759
760
int
761
cmd_set_tile_phase(gx_device_clist_writer * cldev, gx_clist_state * pcls,
762
                   int px, int py)
763
0
{
764
0
    return cmd_set_tile_phase_generic(cldev, pcls, px, py, false);
765
0
}
766
767
int
768
cmd_set_screen_phase_generic(gx_device_clist_writer * cldev, gx_clist_state * pcls,
769
                             int px, int py, gs_color_select_t color_select,
770
                             bool all_bands)
771
5
{
772
5
    int pcsize;
773
5
    byte *dp;
774
5
    int code;
775
776
5
    pcsize = 1 + cmd_size2w(px, py);
777
5
    if (all_bands)
778
5
        code = set_cmd_put_all_op(&dp, cldev, (byte)cmd_opv_set_screen_phaseT + color_select, pcsize);
779
0
    else
780
0
        code = set_cmd_put_op(&dp, cldev, pcls, (byte)cmd_opv_set_screen_phaseT + color_select, pcsize);
781
5
    if (code < 0)
782
0
        return code;
783
5
    ++dp;
784
5
    pcls->screen_phase[color_select].x = px;
785
5
    pcls->screen_phase[color_select].y = py;
786
5
    cmd_putxy(pcls->screen_phase[color_select], &dp);
787
5
    return 0;
788
5
}
789
790
int
791
cmd_set_screen_phase(gx_device_clist_writer * cldev, gx_clist_state * pcls,
792
                     int px, int py, gs_color_select_t color_select)
793
0
{
794
0
    return cmd_set_screen_phase_generic(cldev, pcls, px, py, color_select, false);
795
0
}
796
797
/* Write a command to enable or disable the logical operation. */
798
int
799
cmd_put_enable_lop(gx_device_clist_writer * cldev, gx_clist_state * pcls,
800
                   int enable)
801
102k
{
802
102k
    byte *dp;
803
102k
    int code = set_cmd_put_op(&dp, cldev, pcls,
804
102k
                              (byte)(enable ? cmd_opv_enable_lop :
805
102k
                                     cmd_opv_disable_lop),
806
102k
                              1);
807
808
102k
    if (code < 0)
809
0
        return code;
810
102k
    pcls->lop_enabled = enable;
811
102k
    return 0;
812
102k
}
813
814
/* Write a command to enable or disable clipping. */
815
/* This routine is only called if the path extensions are included. */
816
int
817
cmd_put_enable_clip(gx_device_clist_writer * cldev, gx_clist_state * pcls,
818
                    int enable)
819
421
{
820
421
    byte *dp;
821
421
    int code = set_cmd_put_op(&dp, cldev, pcls,
822
421
                              (byte)(enable ? cmd_opv_enable_clip :
823
421
                                     cmd_opv_disable_clip),
824
421
                              1);
825
826
421
    if (code < 0)
827
0
        return code;
828
421
    pcls->clip_enabled = enable;
829
421
    return 0;
830
421
}
831
832
/* Write a command to set the logical operation. */
833
int
834
cmd_set_lop(gx_device_clist_writer * cldev, gx_clist_state * pcls,
835
            gs_logical_operation_t lop)
836
188k
{
837
188k
    byte *dp;
838
188k
    uint lop_msb = lop >> 6;
839
188k
    int code = set_cmd_put_op(&dp, cldev, pcls,
840
188k
                              cmd_opv_set_misc, 2 + cmd_size_w(lop_msb));
841
842
188k
    if (code < 0)
843
0
        return code;
844
188k
    dp[1] = cmd_set_misc_lop + (lop & 0x3f);
845
188k
    cmd_put_w(lop_msb, dp + 2);
846
188k
    pcls->lop = lop;
847
188k
    return 0;
848
188k
}
849
850
/* Disable (if default) or enable the logical operation, setting it if */
851
/* needed. */
852
int
853
cmd_update_lop(gx_device_clist_writer *cldev, gx_clist_state *pcls,
854
               gs_logical_operation_t lop)
855
2.96M
{
856
2.96M
    int code;
857
858
2.96M
    if (lop == lop_default)
859
2.77M
        return cmd_disable_lop(cldev, pcls);
860
188k
    code = cmd_set_lop(cldev, pcls, lop);
861
188k
    if (code < 0)
862
0
        return code;
863
188k
    return cmd_enable_lop(cldev, pcls);
864
188k
}
865
866
/* Write a parameter list */
867
int /* ret 0 all ok, -ve error */
868
cmd_put_params(gx_device_clist_writer *cldev,
869
               gs_param_list *param_list) /* NB open for READ */
870
0
{
871
0
    byte *dp;
872
0
    int code;
873
0
    byte local_buf[512];  /* arbitrary */
874
0
    int param_length;
875
876
    /* Get serialized list's length + try to get it into local var if it fits. */
877
0
    param_length = code =
878
0
        gs_param_list_serialize(param_list, local_buf, sizeof(local_buf));
879
0
    if (param_length > 0) {
880
        /* Get cmd buffer space for serialized */
881
0
        code = set_cmd_put_all_extended_op(&dp, cldev, cmd_opv_ext_put_params,
882
0
                                  2 + sizeof(unsigned) + param_length);
883
0
        if (code < 0)
884
0
            return code;
885
886
        /* write param list to cmd list: needs to all fit in cmd buffer */
887
0
        if_debug1m('l', cldev->memory, "[l]put_params, length=%d\n", param_length);
888
0
        dp += 2;
889
0
        memcpy(dp, &param_length, sizeof(unsigned));
890
0
        dp += sizeof(unsigned);
891
0
        if (param_length > sizeof(local_buf)) {
892
0
            int old_param_length = param_length;
893
894
0
            param_length = code =
895
0
                gs_param_list_serialize(param_list, dp, old_param_length);
896
0
            if (param_length >= 0)
897
0
                code = (old_param_length != param_length ?
898
0
                        gs_note_error(gs_error_unknownerror) : 0);
899
0
            if (code < 0) {
900
                /* error serializing: back out by writing a 0-length parm list */
901
0
                memset(dp - sizeof(unsigned), 0, sizeof(unsigned));
902
0
                cmd_shorten_list_op(cldev, cldev->band_range_list,
903
0
                                    old_param_length);
904
0
            }
905
0
        } else
906
0
            memcpy(dp, local_buf, param_length);     /* did this when computing length */
907
0
    }
908
0
    return code;
909
0
}
910
911
/* Initialize CCITTFax filters. */
912
static void
913
clist_cf_init(stream_CF_state *ss, int width)
914
175k
{
915
175k
    ss->K = -1;
916
175k
    ss->Columns = width;
917
#if 0 /* Disabled due to a crash with ppmraw -r216 c327.bin :
918
         the decoding filter overruns in 1 byte.
919
       */
920
    ss->EndOfBlock = false;
921
#else
922
175k
    ss->EndOfBlock = true;
923
175k
#endif
924
175k
    ss->BlackIs1 = true;
925
175k
    ss->DecodedByteAlign = align_bitmap_mod;
926
175k
}
927
void
928
clist_cfe_init(stream_CFE_state *ss, int width, gs_memory_t *mem)
929
91.9k
{
930
91.9k
    s_init_state((stream_state *)ss, &s_CFE_template, mem);
931
91.9k
    s_CFE_set_defaults_inline(ss);
932
91.9k
    clist_cf_init((stream_CF_state *)ss, width);
933
91.9k
    s_CFE_template.init((stream_state *)(ss));
934
91.9k
}
935
void
936
clist_cfd_init(stream_CFD_state *ss, int width, int height, gs_memory_t *mem)
937
83.5k
{
938
83.5k
    s_init_state((stream_state *)ss, &s_CFD_template, mem);
939
83.5k
    s_CFD_template.set_defaults((stream_state *)ss);
940
83.5k
    clist_cf_init((stream_CF_state *)ss, width);
941
83.5k
    ss->Rows = height;
942
83.5k
    s_CFD_template.init((stream_state *)(ss));
943
83.5k
}
944
945
/* Initialize RunLength filters. */
946
void
947
clist_rle_init(stream_RLE_state *ss)
948
60.6k
{
949
60.6k
    s_init_state((stream_state *)ss, &s_RLE_template, (gs_memory_t *)0);
950
60.6k
    ss->templat->set_defaults((stream_state *)ss);
951
60.6k
    ss->templat->init((stream_state *)ss);
952
60.6k
}
953
void
954
clist_rld_init(stream_RLD_state *ss)
955
0
{
956
0
    s_init_state((stream_state *)ss, &s_RLD_template, (gs_memory_t *)0);
957
0
    ss->templat->set_defaults((stream_state *)ss);
958
0
    ss->templat->init((stream_state *)ss);
959
0
}
960
961
/* Read a transformation matrix. */
962
const byte *
963
cmd_read_matrix(gs_matrix * pmat, const byte * cbp)
964
615k
{
965
615k
    stream s;
966
967
615k
    s_init(&s, NULL);
968
615k
    sread_string(&s, cbp, 1 + sizeof(*pmat));
969
615k
    sget_matrix(&s, pmat);
970
615k
    return cbp + stell(&s);
971
615k
}
972
973
/*
974
Some notes on understanding the output of -ZL.
975
976
The examples here are given from:
977
  gs -o out.png -r96 -sDEVICE=png16m -dBandHeight=20 -dMaxBitmap=1000 -ZL examples/tiger.eps
978
979
Not every line in that output is explained here!
980
981
When writing a command list, we gather up a list of 'commands' into the
982
clist (cfile). We then have a series of indexes that says which of these
983
commands is needed for each band (bfile).
984
985
So, while writing, we can be writing for 1 band, or for a range of bands
986
at any given time. Commands that follow one another for the same band
987
(or range of bands) will be crammed together into a single command block.
988
These command blocks are each given an id for debugging purposes. When
989
the set of bands for which we are writing changes, the id changes.
990
991
Somewhere towards the top of the output (i.e. within a
992
hundred lines or so) you should see:
993
994
  [L]Resetting: Band range(0,56)
995
996
So, we are writing some commands that will apply to bands 0 to 56.
997
998
  [L] id:0+0, put_fill_dcolor(13)
999
  [L] id:0+13, fill_rect 0(5)
1000
1001
So, for id 0, at 0 bytes offset, we first have a put_fill_dcolor command
1002
that takes 13 bytes. Then, still in id 0, at 13 bytes offset, we have
1003
a fill_rect that takes 5 bytes.
1004
1005
Then we change the band:
1006
1007
  [L]Change to band=0, align=6
1008
1009
When we change the band, we change to a new command block, and the id
1010
changes - so you'll see the subsequent entries listed with id 1.
1011
Subsequent command blocks are aligned, so you'll see some alignment
1012
(padding) bytes used - here 6 bytes.
1013
1014
  [L] id:1+0, set_misc2(6)
1015
  [L] id:1+6, begin_clip(1)
1016
  [L] id:1+7, fill_rect 0(7)
1017
1018
Here we see various commands, each for id 1, at the expected offsets
1019
given their respective sizes. Then we get some debugging from elsewhere
1020
in the clist system.
1021
1022
[L]  r6:0,793,0,1123
1023
1024
This indicates details about the fill_rect (in particular the way
1025
the fill_rect is encoded, and the parameters it uses). Such lines can
1026
be differentiated fairly easily from the command block writing code
1027
as they do not start with 'id:'.
1028
1029
We continue with more commands:
1030
1031
  [L] id:1+14, end_clip(1)
1032
  [L] id:1+15, put_fill_dcolor(13)
1033
  [L]  rmoveto:0: 0 0
1034
  [L] id:1+28, rmoveto(5)
1035
  [L]  rlineto:0: 0 1123
1036
  [L] id:1+33, vlineto(4)
1037
  [L]  rlineto:0: 793 0
1038
  [L] id:1+37, hlineto(3)
1039
  [L]  rlineto:0: 0 -1123
1040
  [L] id:1+40, vlineto(4)
1041
  [L]  closepath:0:
1042
  [L] id:1+44, closepath(1)
1043
  [L] id:1+45, fill(1)
1044
1045
Here we note a couple of things. The clist command encoding system
1046
works by first reserving the required number of bytes for a command,
1047
then filling in those bytes. Because lots of parameters vary in length
1048
according to their particular value, we often have to do a lot of the
1049
encoding work twice; once to count how many bytes we need to reserve
1050
and then once to fill in the block.
1051
1052
The command buffer debug lines (i.e. the ones starting 'id:') are output
1053
at the point the buffer is reserved. Other debug lines for the same
1054
command can happen either before or after these lines. So the 'r6' line
1055
happened after the command reservation that it corresponded to, whereas
1056
the 'rmoveto' (and others) above happen before the command reservation.
1057
This can be confusing.
1058
1059
Another confusing thing is that the commands can appear to change. The
1060
non-command block debug above mentions 4 rlineto's, but these all
1061
appear in the command list as vlineto or hlineto. This is because
1062
the command block queueing attempts to be smart and to simplify the
1063
sequence of commands. This can mean pulling a command into a previous
1064
one, or (as in this case) realising that a simpler encoding can be
1065
used.
1066
1067
And we continue...
1068
1069
  [L]Change to band=1, align=2
1070
  [L] id:2+0, set_misc2(6)
1071
  [L] id:2+6, begin_clip(1)
1072
1073
After a while, we move to an output phase where things are actually
1074
written to the file. These come in groups like:
1075
1076
  [l]writing for bands (0,56) at 0
1077
  [L] cmd id=0 at 0
1078
  [L] adding terminator, end_run(1)
1079
1080
So this is writing out a note that bands 0 to 56 should execute the following
1081
id's. We then write out the id's in question (id 0, goes into cfile at offset 0).
1082
This is then terminated by a single byte 'end_run' marker.
1083
1084
This repeats, with the file offsets increasing as we go. Some cases have more
1085
than one id, for instance:
1086
1087
  [l]writing for bands (7,7) at 640
1088
  [L] cmd id=8 at 640
1089
  [L] cmd id=194 at 685
1090
  [L] cmd id=215 at 785
1091
  [L] cmd id=712 at 928
1092
  [L] cmd id=720 at 969
1093
  [L] cmd id=726 at 986
1094
  [L] cmd id=732 at 1016
1095
  [L] cmd id=809 at 1046
1096
  [L] cmd id=817 at 1185
1097
  [L] cmd id=822 at 1258
1098
  [L] adding terminator, end_page(1)
1099
1100
So, by matching up the id's in this section, together with their offsets,
1101
we can find out what command was written there.
1102
1103
For instance, suppose we hit a problem when reading the cfile at offset 1029.
1104
We can look to see that this is id=732 + 13 bytes. We can look back in the
1105
output to where id:732 was being output, and we see:
1106
1107
  [L] id:732+13, rmoveto(5)
1108
1109
Most clist bugs tend to involve the reader and writer disagreeing on how
1110
many bytes a given command should be and getting out of step. By looking at
1111
where the writer puts stuff, and the reader is trying to read stuff, we can
1112
hopefully spot this.
1113
1114
The writing phase ends with:
1115
1116
  [l]writing pseudo band 57 cb pos 92521
1117
  [l]writing 1824 bytes into cfile at 92521
1118
  [l]writing end for bands (-1,-1) at 94345
1119
1120
FIXME: Explain the pseudo band.
1121
1122
The next section of the logging shows the reader reading. For each band
1123
in turn, we'll see a section where we announce what band we are
1124
rendering:
1125
1126
  [l]rendering bands (0,0)
1127
1128
Then we will read through the different band records that were output
1129
above.
1130
1131
  [l]reading for bands (0,0) at bfile 0, cfile 0, length 0
1132
  [l]reading for bands (0,56) at bfile 16, cfile 0, length 19
1133
  [l]reading for bands (0,0) at bfile 32, cfile 19, length 47
1134
1135
If we look back, we can see that the first of these corresponded to an
1136
empty record. The second of these corresponded to the write of
1137
"cmd id=0 at 0", and the third corresponds to the write of
1138
"cmd id=1 at 19".
1139
1140
When these records have been read in, we actually execute the data. Each
1141
line gives the offset from which the command was read (which allows us
1142
to track it back to what it *should* be in the case of a mismatch),
1143
and is followed by the command name, and a selection of its parameters:
1144
1145
  [L] 0: put_fill_dcolor cmd_opv_ext_put_drawing_color
1146
  [L] 13: fill_rect 0 x=0 y=0 w=0 h=0
1147
  [L] 18: end_run
1148
  [L] 19: set_misc2
1149
  [L]      CJ=-1 AC=1 SA=1
1150
  [L]      BM=0 TK=1 OPM=0 OP=0 op=0 RI=1
1151
  [L] 25: begin_clip
1152
  [L] 26: fill_rect 0 x=0 y=0 w=793 h=1123
1153
  [L] 33: end_clip
1154
  [L] 34: put_fill_dcolor cmd_opv_ext_put_drawing_color
1155
  [L] 47: rmoveto (0,0) 0 0
1156
  [L] 52: vlineto 1123
1157
  [L] 56: hlineto 793
1158
  [L] 59: vlineto -1123
1159
  [L] 63: closepath
1160
  [L] 64: fill
1161
  [L] 65: end_page
1162
1163
Then we repeat gathering the data for the next band:
1164
1165
  [l]rendering bands (1,1)
1166
  [l]reading for bands (0,56) at bfile 16, cfile 0, length 19
1167
  [l]reading for bands (1,1) at bfile 48, cfile 66, length 46
1168
1169
and so on.
1170
1171
*/