Coverage Report

Created: 2025-06-10 07:26

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