Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gxht.c
Line
Count
Source
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Halftone rendering for imaging library */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gsstruct.h"
22
#include "gsbitops.h"
23
#include "gsutil.h"   /* for gs_next_ids */
24
#include "gxdcolor.h"
25
#include "gxfixed.h"
26
#include "gxdevice.h"   /* for gzht.h */
27
#include "gxgstate.h"
28
#include "gzht.h"
29
#include "gsserial.h"
30
31
/* Define the binary halftone device color type. */
32
/* The type descriptor must be public for Pattern types. */
33
gs_public_st_composite(st_dc_ht_binary, gx_device_color, "dc_ht_binary",
34
                       dc_ht_binary_enum_ptrs, dc_ht_binary_reloc_ptrs);
35
static dev_color_proc_save_dc(gx_dc_ht_binary_save_dc);
36
static dev_color_proc_get_dev_halftone(gx_dc_ht_binary_get_dev_halftone);
37
static dev_color_proc_load(gx_dc_ht_binary_load);
38
static dev_color_proc_fill_rectangle(gx_dc_ht_binary_fill_rectangle);
39
static dev_color_proc_fill_masked(gx_dc_ht_binary_fill_masked);
40
static dev_color_proc_equal(gx_dc_ht_binary_equal);
41
static dev_color_proc_write(gx_dc_ht_binary_write);
42
static dev_color_proc_read(gx_dc_ht_binary_read);
43
const gx_device_color_type_t
44
      gx_dc_type_data_ht_binary =
45
{&st_dc_ht_binary,
46
 gx_dc_ht_binary_save_dc, gx_dc_ht_binary_get_dev_halftone,
47
 gx_dc_ht_get_phase,
48
 gx_dc_ht_binary_load, gx_dc_ht_binary_fill_rectangle,
49
 gx_dc_ht_binary_fill_masked, gx_dc_ht_binary_equal,
50
 gx_dc_ht_binary_write, gx_dc_ht_binary_read,
51
 gx_dc_ht_binary_get_nonzero_comps
52
};
53
54
#undef gx_dc_type_ht_binary
55
const gx_device_color_type_t *const gx_dc_type_ht_binary =
56
&gx_dc_type_data_ht_binary;
57
58
8.99M
#define gx_dc_type_ht_binary (&gx_dc_type_data_ht_binary)
59
/* GC procedures */
60
static
61
303k
ENUM_PTRS_WITH(dc_ht_binary_enum_ptrs, gx_device_color *cptr) return 0;
62
101k
ENUM_PTR(0, gx_device_color, colors.binary.b_ht);
63
101k
case 1:
64
101k
{
65
101k
    gx_ht_tile *tile = cptr->colors.binary.b_tile;
66
67
101k
    ENUM_RETURN(tile ? tile - tile->index : 0);
68
0
}
69
303k
ENUM_PTRS_END
70
101k
static RELOC_PTRS_WITH(dc_ht_binary_reloc_ptrs, gx_device_color *cptr)
71
101k
{
72
101k
    gx_ht_tile *tile = cptr->colors.binary.b_tile;
73
101k
    uint index = tile ? tile->index : 0;
74
75
101k
    RELOC_PTR(gx_device_color, colors.binary.b_ht);
76
101k
    RELOC_TYPED_OFFSET_PTR(gx_device_color, colors.binary.b_tile, index);
77
101k
}
78
101k
RELOC_PTRS_END
79
#undef cptr
80
81
/* Other GC procedures */
82
private_st_ht_tiles();
83
static
84
ENUM_PTRS_BEGIN_PROC(ht_tiles_enum_ptrs)
85
2.68M
{
86
2.68M
    return 0;
87
2.68M
}
88
ENUM_PTRS_END_PROC
89
2.68M
static RELOC_PTRS_BEGIN(ht_tiles_reloc_ptrs)
90
2.68M
{
91
    /* Reset the bitmap pointers in the tiles. */
92
    /* We know the first tile points to the base of the bits. */
93
2.68M
    gx_ht_tile *ht_tiles = vptr;
94
2.68M
    byte *bits = ht_tiles->tiles.data;
95
2.68M
    uint diff;
96
97
2.68M
    if (bits == 0)
98
0
        return;
99
2.68M
    RELOC_VAR(bits);
100
2.68M
    if (size == size_of(gx_ht_tile)) { /* only 1 tile */
101
0
        ht_tiles->tiles.data = bits;
102
0
        return;
103
0
    }
104
2.68M
    diff = ht_tiles[1].tiles.data - ht_tiles[0].tiles.data;
105
2.34G
    for (; size; ht_tiles++, size -= size_of(gx_ht_tile), bits += diff) {
106
2.34G
        ht_tiles->tiles.data = bits;
107
2.34G
    }
108
2.68M
}
109
2.68M
RELOC_PTRS_END
110
private_st_ht_cache();
111
112
/* Return the default sizes of the halftone cache. */
113
uint
114
gx_ht_cache_default_tiles(void)
115
0
{
116
#ifdef DEBUG
117
    return (gs_debug_c('.') ? max_ht_cached_tiles_SMALL :
118
            max_ht_cached_tiles);
119
#else
120
0
    return max_ht_cached_tiles;
121
0
#endif
122
0
}
123
uint
124
gx_ht_cache_default_bits_size(void)
125
7.26M
{
126
#ifdef DEBUG
127
    return (gs_debug_c('.') ? max_ht_cache_bits_size_SMALL :
128
            max_ht_cache_bits_size);
129
#else
130
7.26M
    return max_ht_cache_bits_size;
131
7.26M
#endif
132
7.26M
}
133
134
/* Allocate a halftone cache. max_bits_size is number of bytes */
135
gx_ht_cache *
136
gx_ht_alloc_cache(gs_memory_t * mem, uint max_tiles, uint max_bits_size)
137
5.43M
{
138
5.43M
    gx_ht_cache *pcache =
139
5.43M
    gs_alloc_struct(mem, gx_ht_cache, &st_ht_cache,
140
5.43M
                    "alloc_ht_cache(struct)");
141
5.43M
    byte *tbits =
142
5.43M
        gs_alloc_bytes(mem, max_bits_size, "alloc_ht_cache(bits)");
143
5.43M
    gx_ht_tile *ht_tiles =
144
5.43M
        gs_alloc_struct_array(mem, max_tiles, gx_ht_tile, &st_ht_tiles,
145
5.43M
                              "alloc_ht_cache(ht_tiles)");
146
147
5.43M
    if (pcache == 0 || tbits == 0 || ht_tiles == 0) {
148
9
        gs_free_object(mem, ht_tiles, "alloc_ht_cache(ht_tiles)");
149
9
        gs_free_object(mem, tbits, "alloc_ht_cache(bits)");
150
9
        gs_free_object(mem, pcache, "alloc_ht_cache(struct)");
151
9
        return 0;
152
9
    }
153
5.43M
    pcache->bits = tbits;
154
5.43M
    pcache->bits_size = max_bits_size;
155
5.43M
    pcache->ht_tiles = ht_tiles;
156
5.43M
    pcache->num_tiles = max_tiles;
157
5.43M
    pcache->order.cache = pcache;
158
5.43M
    pcache->order.transfer = 0;
159
5.43M
    gx_ht_clear_cache(pcache);
160
5.43M
    return pcache;
161
5.43M
}
162
163
/* Free a halftone cache. */
164
void
165
gx_ht_free_cache(gs_memory_t * mem, gx_ht_cache * pcache)
166
5.43M
{
167
5.43M
    gs_free_object(mem, pcache->ht_tiles, "free_ht_cache(ht_tiles)");
168
5.43M
    gs_free_object(mem, pcache->bits, "free_ht_cache(bits)");
169
5.43M
    gs_free_object(mem, pcache, "free_ht_cache(struct)");
170
5.43M
}
171
172
/* Render a given level into a halftone cache. */
173
static int render_ht(gx_ht_tile *, int, const gx_ht_order *,
174
                      gx_bitmap_id);
175
static gx_ht_tile *
176
gx_render_ht_default(gx_ht_cache * pcache, int b_level)
177
606M
{
178
606M
    const gx_ht_order *porder = &pcache->order;
179
606M
    int level = porder->levels[b_level];
180
606M
    gx_ht_tile *bt;
181
182
606M
    if (pcache->num_cached < porder->num_levels )
183
4.51k
        bt = &pcache->ht_tiles[level / pcache->levels_per_tile];
184
606M
    else
185
606M
        bt =  &pcache->ht_tiles[b_level]; /* one tile per b_level */
186
187
606M
    if (bt->level != level) {
188
2.90M
        int code = render_ht(bt, level, porder, pcache->base_id + b_level);
189
190
2.90M
        if (code < 0)
191
0
            return 0;
192
2.90M
    }
193
606M
    return bt;
194
606M
}
195
196
/* save information about the operand binary halftone color */
197
static void
198
gx_dc_ht_binary_save_dc(const gx_device_color * pdevc,
199
                        gx_device_color_saved * psdc)
200
4.69M
{
201
4.69M
    psdc->type = pdevc->type;
202
4.69M
    psdc->colors.binary.b_color[0] = pdevc->colors.binary.color[0];
203
4.69M
    psdc->colors.binary.b_color[1] = pdevc->colors.binary.color[1];
204
4.69M
    psdc->colors.binary.b_level = pdevc->colors.binary.b_level;
205
4.69M
    psdc->colors.binary.b_index = pdevc->colors.binary.b_index;
206
4.69M
    psdc->phase = pdevc->phase;
207
4.69M
}
208
209
/* get the halftone used for a binary halftone color */
210
static const gx_device_halftone *
211
gx_dc_ht_binary_get_dev_halftone(const gx_device_color * pdevc)
212
58.2M
{
213
58.2M
    return pdevc->colors.binary.b_ht;
214
58.2M
}
215
216
/* Load the device color into the halftone cache if needed. */
217
static int
218
gx_dc_ht_binary_load(gx_device_color * pdevc, const gs_gstate * pgs,
219
                     gx_device * dev, gs_color_select_t select)
220
65.3M
{
221
65.3M
    int component_index = pdevc->colors.binary.b_index;
222
65.3M
    const gx_ht_order *porder;
223
65.3M
    gx_ht_cache *pcache;
224
225
65.3M
    if (component_index < 0) {
226
0
        porder = &pdevc->colors.binary.b_ht->order;
227
65.3M
    } else {
228
65.3M
        int i = 0;
229
230
        /* We can get here with pgs being NULL from the clist. In that case we can't check the saved halftone
231
         * against the graphics state, because there is no graphics state. But I believe it should not be
232
         * possible for this to cause a problem with the clist.
233
         */
234
65.3M
        if (pgs != NULL) {
235
            /* Ensure the halftone saved in the device colour matches one of the
236
             * object-type device halftones. It should not be possible for this not
237
             * to be the case, but an image with a procedural data source which executes
238
             * more grestores than gsaves can restore away the halftone that was in
239
             * force at the start of the image, while we're trying to still use it.
240
             * If that happens we cna't do anything but throw an error.
241
             */
242
65.3M
            for (i=0;i < HT_OBJTYPE_COUNT;i++) {
243
65.3M
                if (pdevc->colors.binary.b_ht == pgs->dev_ht[i])
244
65.3M
                    break;
245
65.3M
            }
246
65.3M
            if (i == HT_OBJTYPE_COUNT)
247
0
                return_error(gs_error_unknownerror);
248
65.3M
        }
249
65.3M
        porder = &pdevc->colors.binary.b_ht->components[component_index].corder;
250
251
65.3M
    }
252
65.3M
    pcache = porder->cache;
253
65.3M
    if (pcache->order.bit_data != porder->bit_data) {
254
        /* I don't think this should be possible, but just in case */
255
0
        if (pgs == NULL)
256
0
            return_error(gs_error_unknownerror);
257
0
        gx_ht_init_cache(pgs->memory, pcache, porder);
258
0
    }
259
    /*
260
     * We do not load the cache now.  Instead we wait until we are ready
261
     * to actually render the color.  This allows multiple colors to be
262
     * loaded without cache conflicts.  (Cache conflicts can occur when
263
     * if two device colors use the same cache elements.  This can occur
264
     * when the tile size is large enough that we do not have a separate
265
     * tile for each half tone level.)  See gx_dc_ht_binary_load_cache.
266
     */
267
65.3M
    pdevc->colors.binary.b_tile = NULL;
268
65.3M
    return 0;
269
65.3M
}
270
271
/*
272
 * Load the half tone tile in the halftone cache.
273
 */
274
static int
275
gx_dc_ht_binary_load_cache(const gx_device_color * pdevc)
276
226M
{
277
226M
    int component_index = pdevc->colors.binary.b_index;
278
226M
    const gx_ht_order *porder =
279
226M
         &pdevc->colors.binary.b_ht->components[component_index].corder;
280
226M
    gx_ht_cache *pcache = porder->cache;
281
226M
    int b_level = pdevc->colors.binary.b_level;
282
226M
    int level = porder->levels[b_level];
283
226M
    gx_ht_tile *bt;
284
285
226M
    if (pcache->num_cached < porder->num_levels )
286
0
        bt = &pcache->ht_tiles[level / pcache->levels_per_tile];
287
226M
    else
288
226M
        bt =  &pcache->ht_tiles[b_level]; /* one tile per b_level */
289
290
226M
    if (bt->level != level) {
291
181k
        int code = render_ht(bt, level, porder, pcache->base_id + b_level);
292
293
181k
        if (code < 0)
294
0
            return_error(gs_error_Fatal);
295
181k
    }
296
226M
    ((gx_device_color *)pdevc)->colors.binary.b_tile = bt;
297
226M
    return 0;
298
226M
}
299
300
/* Fill a rectangle with a binary halftone. */
301
/* Note that we treat this as "texture" for RasterOp. */
302
static int
303
gx_dc_ht_binary_fill_rectangle(const gx_device_color * pdevc, int x, int y,
304
                  int w, int h, gx_device * dev, gs_logical_operation_t lop,
305
                               const gx_rop_source_t * source)
306
1.99G
{
307
1.99G
    gx_rop_source_t no_source;
308
309
1.99G
    fit_fill(dev, x, y, w, h);
310
    /* Load the halftone cache for the color */
311
221M
    gx_dc_ht_binary_load_cache(pdevc);
312
    /*
313
     * Observation of H-P devices and documentation yields confusing
314
     * evidence about whether white pixels in halftones are always
315
     * opaque.  It appears that for black-and-white devices, these
316
     * pixels are *not* opaque.
317
     */
318
221M
    if (dev->color_info.depth > 1)
319
98.6M
        lop &= ~lop_T_transparent;
320
221M
    if (source == NULL && lop_no_S_is_T(lop))
321
221M
        return (*dev_proc(dev, strip_tile_rectangle)) (dev,
322
221M
                                        &pdevc->colors.binary.b_tile->tiles,
323
221M
                                  x, y, w, h, pdevc->colors.binary.color[0],
324
221M
                                              pdevc->colors.binary.color[1],
325
221M
                                            pdevc->phase.x, pdevc->phase.y);
326
    /* Adjust the logical operation per transparent colors. */
327
0
    if (pdevc->colors.binary.color[0] == gx_no_color_index)
328
0
        lop = rop3_use_D_when_T_0(lop);
329
0
    if (pdevc->colors.binary.color[1] == gx_no_color_index)
330
0
        lop = rop3_use_D_when_T_1(lop);
331
0
    if (source == NULL)
332
0
        set_rop_no_source(source, no_source, dev);
333
0
    return (*dev_proc(dev, strip_copy_rop2))
334
0
                             (dev, source->sdata,
335
0
                              source->sourcex, source->sraster, source->id,
336
0
                              (source->use_scolors ? source->scolors : NULL),
337
0
                              &pdevc->colors.binary.b_tile->tiles,
338
0
                              pdevc->colors.binary.color,
339
0
                              x, y, w, h, pdevc->phase.x, pdevc->phase.y,
340
0
                              lop, source->planar_height);
341
221M
}
342
343
static int
344
gx_dc_ht_binary_fill_masked(const gx_device_color * pdevc, const byte * data,
345
        int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h,
346
                   gx_device * dev, gs_logical_operation_t lop, bool invert)
347
5.17M
{
348
    /*
349
     * Load the halftone cache for the color.  We do not do it earlier
350
     * because for small halftone caches, each cache tile may be used for
351
     * for more than one halftone level.  This can cause conflicts if more
352
     * than one device color has been set and they use the same cache
353
     * entry.
354
     */
355
5.17M
    int code = gx_dc_ht_binary_load_cache(pdevc);
356
357
5.17M
    if (code < 0)
358
0
        return code;
359
5.17M
    return gx_dc_default_fill_masked(pdevc, data, data_x, raster, id,
360
5.17M
                                        x, y, w, h, dev, lop, invert);
361
5.17M
}
362
363
/* Compare two binary halftones for equality. */
364
static bool
365
gx_dc_ht_binary_equal(const gx_device_color * pdevc1,
366
                      const gx_device_color * pdevc2)
367
14.9M
{
368
14.9M
    return pdevc2->type == pdevc1->type &&
369
10.4M
        pdevc1->phase.x == pdevc2->phase.x &&
370
10.4M
        pdevc1->phase.y == pdevc2->phase.y &&
371
10.4M
        gx_dc_binary_color0(pdevc1) == gx_dc_binary_color0(pdevc2) &&
372
9.76M
        gx_dc_binary_color1(pdevc1) == gx_dc_binary_color1(pdevc2) &&
373
9.69M
        pdevc1->colors.binary.b_level == pdevc2->colors.binary.b_level;
374
14.9M
}
375
376
/*
377
 * Flags to indicate the pieces of a binary halftone that are included
378
 * in its string representation. The first byte of the string holds this
379
 * set of flags.
380
 *
381
 * The binary halftone tile is never transmitted as part of the string
382
 * representation, so there is also no flag bit for it.
383
 */
384
enum {
385
    dc_ht_binary_has_color0 = 0x01,
386
    dc_ht_binary_has_color1 = 0x02,
387
    dc_ht_binary_has_level = 0x04,
388
    dc_ht_binary_has_index = 0x08,
389
    dc_ht_binary_has_phase_x = 0x10,
390
    dc_ht_binary_has_phase_y = 0x20,
391
};
392
393
/*
394
 * Serialize a binany halftone device color.
395
 *
396
 * Operands:
397
 *
398
 *  pdevc       pointer to device color to be serialized
399
 *
400
 *  psdc        pointer ot saved version of last serialized color (for
401
 *              this band)
402
 *
403
 *  dev         pointer to the current device, used to retrieve process
404
 *              color model information
405
 *
406
 *  pdata       pointer to buffer in which to write the data
407
 *
408
 *  psize       pointer to a location that, on entry, contains the size of
409
 *              the buffer pointed to by pdata; on return, the size of
410
 *              the data required or actually used will be written here.
411
 *
412
 * Returns:
413
 *  1, with *psize set to 0, if *psdc and *pdevc represent the same color
414
 *
415
 *  0, with *psize set to the amount of data written, if everything OK
416
 *
417
 *  gs_error_rangecheck, with *psize set to the size of buffer required,
418
 *  if *psize was not large enough
419
 *
420
 *  < 0, != gs_error_rangecheck, in the event of some other error; in this
421
 *  case *psize is not changed.
422
 */
423
static int
424
gx_dc_ht_binary_write(
425
    const gx_device_color *         pdevc,
426
    const gx_device_color_saved *   psdc0,
427
    const gx_device *               dev,
428
    int64_t         offset,
429
    byte *                          pdata,
430
    uint *                          psize )
431
62.9M
{
432
62.9M
    int                             req_size = 1;   /* flag bits */
433
62.9M
    int                             flag_bits = 0;
434
62.9M
    uint                            tmp_size;
435
62.9M
    byte *                          pdata0 = pdata;
436
62.9M
    const gx_device_color_saved *   psdc = psdc0;
437
62.9M
    int                             code;
438
439
62.9M
    if (offset != 0)
440
0
        return_error(gs_error_unregistered); /* Not implemented yet. */
441
442
    /* check if operand and saved colors are the same type */
443
62.9M
    if (psdc != 0 && psdc->type != pdevc->type)
444
1.13M
        psdc = 0;
445
446
    /* check for the information that must be transmitted */
447
62.9M
    if ( psdc == 0                                                      ||
448
61.7M
         pdevc->colors.binary.color[0] != psdc->colors.binary.b_color[0]  ) {
449
1.19M
        flag_bits |= dc_ht_binary_has_color0;
450
1.19M
        tmp_size = 0;
451
1.19M
        (void)gx_dc_write_color( pdevc->colors.binary.color[0],
452
1.19M
                                 dev,
453
1.19M
                                 pdata,
454
1.19M
                                 &tmp_size );
455
1.19M
        req_size += tmp_size;
456
1.19M
    }
457
62.9M
    if ( psdc == NULL ||
458
61.7M
         pdevc->colors.binary.color[1] != psdc->colors.binary.b_color[1]  ) {
459
1.19M
        flag_bits |= dc_ht_binary_has_color1;
460
1.19M
        tmp_size = 0;
461
1.19M
        (void)gx_dc_write_color( pdevc->colors.binary.color[1],
462
1.19M
                                 dev,
463
1.19M
                                 pdata,
464
1.19M
                                 &tmp_size );
465
1.19M
        req_size += tmp_size;
466
1.19M
    }
467
468
62.9M
    if ( psdc == NULL ||
469
61.7M
         pdevc->colors.binary.b_level != psdc->colors.binary.b_level  ) {
470
9.37M
        flag_bits |= dc_ht_binary_has_level;
471
9.37M
        req_size += enc_u_sizew(pdevc->colors.binary.b_level);
472
9.37M
    }
473
474
62.9M
    if ( psdc == NULL ||
475
61.7M
         pdevc->colors.binary.b_index != psdc->colors.binary.b_index  ) {
476
1.19M
        flag_bits |= dc_ht_binary_has_index;
477
1.19M
        req_size += 1;
478
1.19M
    }
479
480
62.9M
    if ( psdc == NULL ||
481
61.7M
         pdevc->phase.x != psdc->phase.x ) {
482
1.13M
        flag_bits |= dc_ht_binary_has_phase_x;
483
1.13M
        req_size += enc_u_sizew(pdevc->phase.x);
484
1.13M
    }
485
486
62.9M
    if ( psdc == NULL ||
487
61.7M
         pdevc->phase.y != psdc->phase.y ) {
488
1.13M
        flag_bits |= dc_ht_binary_has_phase_y;
489
1.13M
        req_size += enc_u_sizew(pdevc->phase.y);
490
1.13M
    }
491
492
    /* check if there is anything to be done */
493
62.9M
    if (flag_bits == 0) {
494
53.5M
        *psize = 0;
495
53.5M
        return 1;
496
53.5M
    }
497
498
    /* check if sufficient space has been provided */
499
9.38M
    if (req_size > *psize) {
500
4.69M
        *psize = req_size;
501
4.69M
        return_error(gs_error_rangecheck);
502
4.69M
    }
503
504
    /* write out the flag byte */
505
4.69M
    *pdata++ = (byte)flag_bits;
506
507
    /* write out such other parts of the device color as are required */
508
4.69M
    if ((flag_bits & dc_ht_binary_has_color0) != 0) {
509
599k
        tmp_size = req_size - (pdata - pdata0);
510
599k
        code = gx_dc_write_color( pdevc->colors.binary.color[0],
511
599k
                                  dev,
512
599k
                                  pdata,
513
599k
                                  &tmp_size );
514
599k
        if (code < 0)
515
0
            return code;
516
599k
        pdata += tmp_size;
517
599k
    }
518
4.69M
    if ((flag_bits & dc_ht_binary_has_color1) != 0) {
519
598k
        tmp_size = req_size - (pdata - pdata0);
520
598k
        code = gx_dc_write_color( pdevc->colors.binary.color[1],
521
598k
                                  dev,
522
598k
                                  pdata,
523
598k
                                  &tmp_size );
524
598k
        if (code < 0)
525
0
            return code;
526
598k
        pdata += tmp_size;
527
598k
    }
528
4.69M
    if ((flag_bits & dc_ht_binary_has_level) != 0)
529
4.69M
        enc_u_putw(pdevc->colors.binary.b_level, pdata);
530
4.69M
    if ((flag_bits & dc_ht_binary_has_index) != 0)
531
599k
        *pdata++ = pdevc->colors.binary.b_index;
532
4.69M
    if ((flag_bits & dc_ht_binary_has_phase_x) != 0)
533
4.69M
        enc_u_putw(pdevc->phase.x, pdata);
534
4.69M
    if ((flag_bits & dc_ht_binary_has_phase_y) != 0)
535
4.69M
        enc_u_putw(pdevc->phase.y, pdata);
536
537
4.69M
    *psize = pdata - pdata0;
538
4.69M
    return 0;
539
4.69M
}
540
541
/*
542
 * Reconstruct a binary halftone device color from its serial representation.
543
 *
544
 * Operands:
545
 *
546
 *  pdevc       pointer to the location in which to write the
547
 *              reconstructed device color
548
 *
549
 *  pgs         pointer to the current gs_gstate (to access the
550
 *              current halftone)
551
 *
552
 *  prior_devc  pointer to the current device color (this is provided
553
 *              separately because the device color is not part of the
554
 *              gs_gstate)
555
 *
556
 *  dev         pointer to the current device, used to retrieve process
557
 *              color model information
558
 *
559
 *  pdata       pointer to the buffer to be read
560
 *
561
 *  size        size of the buffer to be read; this should be large
562
 *              enough to hold the entire color description
563
 *
564
 *  mem         pointer to the memory to be used for allocations
565
 *              (ignored here)
566
 *
567
 * Returns:
568
 *
569
 *  # of bytes read if everthing OK, < 0 in the event of an error
570
 */
571
static int
572
gx_dc_ht_binary_read(
573
    gx_device_color *       pdevc,
574
    const gs_gstate        * pgs,
575
    const gx_device_color * prior_devc,
576
    const gx_device *       dev,        /* ignored */
577
    int64_t       offset,
578
    const byte *            pdata,
579
    uint                    size,
580
    gs_memory_t *           mem,        /* ignored */
581
    int                     x0,
582
    int                     y0)
583
4.49M
{
584
4.49M
    gx_device_color         devc;
585
4.49M
    const byte *            pdata0 = pdata;
586
4.49M
    int                     code, flag_bits;
587
588
4.49M
    if (offset != 0)
589
0
        return_error(gs_error_unregistered); /* Not implemented yet. */
590
591
    /* if prior information is available, use it */
592
4.49M
    if (prior_devc != 0 && prior_devc->type == gx_dc_type_ht_binary)
593
4.01M
        devc = *prior_devc;
594
477k
    else
595
477k
        memset(&devc, 0, sizeof(devc));   /* clear pointers */
596
4.49M
    devc.type = gx_dc_type_ht_binary;
597
598
    /* the halftone is always taken from the gs_gstate */
599
4.49M
    devc.colors.binary.b_ht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
600
601
    /* cache is not provided until the device color is used */
602
4.49M
    devc.colors.binary.b_tile = 0;
603
604
    /* verify the minimum amount of information */
605
4.49M
    if (size == 0)
606
0
        return_error(gs_error_rangecheck);
607
4.49M
    size --;
608
4.49M
    flag_bits = *pdata++;
609
610
    /* read the other information provided */
611
4.49M
    if ((flag_bits & dc_ht_binary_has_color0) != 0) {
612
557k
        code = gx_dc_read_color( &devc.colors.binary.color[0],
613
557k
                                 dev,
614
557k
                                 pdata,
615
557k
                                 size );
616
557k
        if (code < 0)
617
0
            return code;
618
557k
        size -= code;
619
557k
        pdata += code;
620
557k
    }
621
4.49M
    if ((flag_bits & dc_ht_binary_has_color1) != 0) {
622
558k
        code = gx_dc_read_color( &devc.colors.binary.color[1],
623
558k
                                 dev,
624
558k
                                 pdata,
625
558k
                                 size );
626
558k
        if (code < 0)
627
0
            return code;
628
558k
        size -= code;
629
558k
        pdata += code;
630
558k
    }
631
4.49M
    if ((flag_bits & dc_ht_binary_has_level) != 0) {
632
4.49M
        const byte *pdata_start = pdata;
633
634
4.49M
        if (size < 1)
635
0
            return_error(gs_error_rangecheck);
636
4.49M
        enc_u_getw(devc.colors.binary.b_level, pdata);
637
4.49M
        size -= pdata - pdata_start;
638
4.49M
    }
639
4.49M
    if ((flag_bits & dc_ht_binary_has_index) != 0) {
640
556k
        if (size == 0)
641
0
            return_error(gs_error_rangecheck);
642
556k
        --size;
643
556k
        devc.colors.binary.b_index = *pdata++;
644
556k
    }
645
4.49M
    if ((flag_bits & dc_ht_binary_has_phase_x) != 0) {
646
533k
        const byte *pdata_start = pdata;
647
648
533k
        if (size < 1)
649
0
            return_error(gs_error_rangecheck);
650
533k
        enc_u_getw(devc.phase.x, pdata);
651
533k
        devc.phase.x += x0;
652
533k
        size -= pdata - pdata_start;
653
533k
    }
654
4.49M
    if ((flag_bits & dc_ht_binary_has_phase_y) != 0) {
655
533k
        const byte *pdata_start = pdata;
656
657
533k
        if (size < 1)
658
0
            return_error(gs_error_rangecheck);
659
533k
        enc_u_getw(devc.phase.y, pdata);
660
533k
        devc.phase.y += y0;
661
533k
        size -= pdata - pdata_start;
662
533k
    }
663
664
    /* everything looks good */
665
4.49M
    *pdevc = devc;
666
4.49M
    return pdata - pdata0;
667
4.49M
}
668
669
/*
670
 * Get the nonzero components of a binary halftone. This is used to
671
 * distinguish components that are given zero intensity due to halftoning
672
 * from those for which the original color intensity was in fact zero.
673
 *
674
 * Since this device color type involves only a single halftone component,
675
 * we can reasonably assume that b_level != 0. Hence, we need to check
676
 * for components with identical intensities in color[0] and color[1].
677
 */
678
int
679
gx_dc_ht_binary_get_nonzero_comps(
680
    const gx_device_color * pdevc,
681
    const gx_device *       dev,
682
    gx_color_index *        pcomp_bits )
683
0
{
684
0
    int                     code;
685
0
    gx_color_value          cvals_0[GX_DEVICE_COLOR_MAX_COMPONENTS],
686
0
                            cvals_1[GX_DEVICE_COLOR_MAX_COMPONENTS];
687
688
0
    if ( (code = dev_proc(dev, decode_color)( (gx_device *)dev,
689
0
                                              pdevc->colors.binary.color[0],
690
0
                                              cvals_0 )) >= 0 &&
691
0
         (code = dev_proc(dev, decode_color)( (gx_device *)dev,
692
0
                                              pdevc->colors.binary.color[1],
693
0
                                              cvals_1 )) >= 0   ) {
694
0
        int     i, ncomps = dev->color_info.num_components;
695
0
        int     mask = 0x1, comp_bits = 0;
696
697
0
        for (i = 0; i < ncomps; i++, mask <<= 1) {
698
0
            if (cvals_0[i] != 0 || cvals_1[i] != 0)
699
0
                comp_bits |= mask;
700
0
        }
701
0
        *pcomp_bits = comp_bits;
702
0
        code = 0;
703
0
    }
704
705
0
    return code;
706
0
}
707
708
/* Initialize the tile cache for a given screen. */
709
/* Cache as many different levels as will fit. */
710
void
711
gx_ht_init_cache(const gs_memory_t *mem, gx_ht_cache * pcache, const gx_ht_order * porder)
712
5.43M
{
713
5.43M
    uint width = porder->width;
714
5.43M
    uint height = porder->height;
715
5.43M
    uint size = width * height + 1;
716
5.43M
    int width_unit =
717
5.43M
    (width <= ht_mask_bits / 2 ? ht_mask_bits / width * width :
718
5.43M
     width);
719
5.43M
    int height_unit = height;
720
5.43M
    uint raster = porder->raster;
721
5.43M
    uint tile_bytes = raster * height;
722
5.43M
    uint shift = porder->shift;
723
5.43M
    int num_cached;
724
5.43M
    int i;
725
5.43M
    byte *tbits = pcache->bits;
726
727
    /* Non-monotonic halftones may have more bits than size. */
728
5.43M
    if (porder->num_bits >= size)
729
0
        size = porder->num_bits + 1;
730
    /* Make sure num_cached is within bounds */
731
5.43M
    num_cached = pcache->bits_size / tile_bytes;
732
5.43M
    if (num_cached > size)
733
5.43M
        num_cached = size;
734
5.43M
    if (num_cached > pcache->num_tiles)
735
0
        num_cached = pcache->num_tiles;
736
5.43M
    if (num_cached == size &&
737
5.43M
        tile_bytes * num_cached <= pcache->bits_size / 2
738
5.43M
        ) {
739
        /*
740
         * We can afford to replicate every tile in the cache,
741
         * which will reduce breakage when tiling.  Since
742
         * horizontal breakage is more expensive than vertical,
743
         * and since wide shallow fills are more common than
744
         * narrow deep fills, we replicate the tile horizontally.
745
         * We do have to be careful not to replicate the tile
746
         * to an absurdly large size, however.
747
         */
748
5.43M
        uint rep_raster =
749
5.43M
        ((pcache->bits_size / num_cached) / height) &
750
5.43M
        ~(align_bitmap_mod - 1);
751
5.43M
        uint rep_count = rep_raster * 8 / width;
752
753
        /*
754
         * There's no real value in replicating the tile
755
         * beyond the point where the byte width of the replicated
756
         * tile is a multiple of a long.
757
         */
758
5.43M
        if (rep_count > sizeof(ulong) * 8)
759
0
            rep_count = sizeof(ulong) * 8;
760
5.43M
        width_unit = width * rep_count;
761
5.43M
        raster = bitmap_raster(width_unit);
762
5.43M
        tile_bytes = raster * height;
763
5.43M
    }
764
5.43M
    pcache->base_id = gs_next_ids(mem, porder->num_levels + 1);
765
5.43M
    pcache->order = *porder;
766
    /* The transfer function is irrelevant, and might become dangling. */
767
5.43M
    pcache->order.transfer = 0;
768
5.43M
    pcache->num_cached = num_cached;
769
5.43M
    pcache->levels_per_tile = (size + num_cached - 1) / num_cached;
770
5.43M
    pcache->tiles_fit = -1;
771
5.43M
    memset(tbits, 0, pcache->bits_size);
772
663M
    for (i = 0; i < num_cached; i++, tbits += tile_bytes) {
773
657M
        register gx_ht_tile *bt = &pcache->ht_tiles[i];
774
775
657M
        bt->level = 0;
776
657M
        bt->index = i;
777
657M
        bt->tiles.data = tbits;
778
657M
        bt->tiles.raster = raster;
779
657M
        bt->tiles.size.x = width_unit;
780
657M
        bt->tiles.size.y = height_unit;
781
657M
        bt->tiles.rep_width = width;
782
657M
        bt->tiles.rep_height = height;
783
657M
        bt->tiles.shift = bt->tiles.rep_shift = shift;
784
657M
        bt->tiles.num_planes = 1;
785
657M
    }
786
5.43M
    pcache->render_ht = gx_render_ht_default;
787
5.43M
}
788
789
/*
790
 * Compute and save the rendering of a given gray level
791
 * with the current halftone.  The cache holds multiple tiles,
792
 * where each tile covers a range of possible levels.
793
 * We adjust the tile whose range includes the desired level incrementally;
794
 * this saves a lot of time for the average image, where gray levels
795
 * don't change abruptly.  Note that the "level" is the number of bits,
796
 * not the index in the levels vector.
797
 */
798
static int
799
render_ht(gx_ht_tile * pbt, int level /* [1..num_bits-1] */ ,
800
          const gx_ht_order * porder, gx_bitmap_id new_id)
801
3.09M
{
802
3.09M
    byte *data = pbt->tiles.data;
803
3.09M
    int code;
804
805
3.09M
    if_debug7('H', "[H]Halftone cache slot "PRI_INTPTR": old=%d, new=%d, w=%d(%d), h=%d(%d):\n",
806
3.09M
              (intptr_t)data, pbt->level, level,
807
3.09M
              pbt->tiles.size.x, porder->width,
808
3.09M
              pbt->tiles.size.y, porder->num_bits / porder->width);
809
#ifdef DEBUG
810
    if (level < 0 || level > porder->num_bits) {
811
        lprintf3("Error in render_ht: level=%d, old level=%d, num_bits=%d\n",
812
                 level, pbt->level, porder->num_bits);
813
        return_error(gs_error_Fatal);
814
    }
815
#endif
816
3.09M
    code = porder->procs->render(pbt, level, porder);
817
3.09M
    if (code < 0)
818
0
        return code;
819
3.09M
    pbt->level = level;
820
3.09M
    pbt->tiles.id = new_id;
821
3.09M
    pbt->tiles.num_planes = 1;
822
    /*
823
     * Check whether we want to replicate the tile in the cache.
824
     * Since we only do this when all the renderings will fit
825
     * in the cache, we only do it once per level, and it doesn't
826
     * have to be very efficient.
827
     */
828
        /****** TEST IS WRONG if width > rep_width but tile.raster ==
829
         ****** order raster.
830
         ******/
831
3.09M
    if (pbt->tiles.raster > porder->raster)
832
3.08M
        bits_replicate_horizontally(data, pbt->tiles.rep_width,
833
3.08M
                                    pbt->tiles.rep_height, porder->raster,
834
3.08M
                                    pbt->tiles.size.x, pbt->tiles.raster);
835
3.09M
    if (pbt->tiles.size.y > pbt->tiles.rep_height &&
836
0
        pbt->tiles.shift == 0
837
3.09M
        )
838
0
        bits_replicate_vertically(data, pbt->tiles.rep_height,
839
0
                                  pbt->tiles.raster, pbt->tiles.size.y);
840
#ifdef DEBUG
841
    if (gs_debug_c('H')) {
842
        const byte *p = pbt->tiles.data;
843
        int wb = pbt->tiles.raster;
844
        const byte *ptr = p + wb * pbt->tiles.size.y;
845
846
        while (p < ptr) {
847
            dmprintf8(porder->data_memory, " %d%d%d%d%d%d%d%d",
848
                      *p >> 7, (*p >> 6) & 1, (*p >> 5) & 1,
849
                      (*p >> 4) & 1, (*p >> 3) & 1, (*p >> 2) & 1,
850
                      (*p >> 1) & 1, *p & 1);
851
            if ((++p - data) % wb == 0)
852
                dmputc(porder->data_memory, '\n');
853
        }
854
    }
855
#endif
856
3.09M
    return 0;
857
3.09M
}