47
47
null_closure_transfer(
49
const gx_transfer_map * pmap_dummy, /* NOTUSED */
50
const void *dummy /* NOTUSED */
49
const gx_transfer_map * pmap_dummy, /* NOTUSED */
50
const void *dummy /* NOTUSED */
58
57
* Build a gs_ht halftone structure.
71
70
/* must have at least one component */
73
72
if (num_comps == 0)
74
return_error(gs_error_rangecheck);
73
return_error(gs_error_rangecheck);
76
75
/* allocate the halftone and the array of components */
77
76
rc_alloc_struct_1(pht,
81
return_error(gs_error_VMerror),
80
return_error(gs_error_VMerror),
84
83
phtc = gs_alloc_struct_array(pmem,
91
gs_free_object(pmem, pht, "gs_ht_build");
92
return_error(gs_error_VMerror);
90
gs_free_object(pmem, pht, "gs_ht_build");
91
return_error(gs_error_VMerror);
94
93
/* initialize the halftone */
95
94
pht->type = ht_type_multiple;
115
114
gs_ht_set_spot_comp(
120
float (*spot_func) (floatp, floatp),
122
gs_ht_transfer_proc transfer,
123
const void *client_data
119
float (*spot_func) (floatp, floatp),
121
gs_ht_transfer_proc transfer,
122
const void *client_data
126
125
gs_ht_component *phtc = &(pht->params.ht_multiple.components[comp]);
128
127
if (comp >= pht->params.ht_multiple.num_comp)
129
return_error(gs_error_rangecheck);
128
return_error(gs_error_rangecheck);
130
129
if (phtc->type != ht_type_none)
131
return_error(gs_error_invalidaccess);
130
return_error(gs_error_invalidaccess);
133
132
phtc->type = ht_type_spot;
134
133
phtc->params.ht_spot.screen.frequency = freq;
152
151
gs_ht_set_threshold_comp(
157
const gs_const_string * thresholds,
158
gs_ht_transfer_proc transfer,
159
const void *client_data
156
const gs_const_string * thresholds,
157
gs_ht_transfer_proc transfer,
158
const void *client_data
162
161
gs_ht_component *phtc = &(pht->params.ht_multiple.components[comp]);
164
163
if (comp >= pht->params.ht_multiple.num_comp)
165
return_error(gs_error_rangecheck);
164
return_error(gs_error_rangecheck);
166
165
if (phtc->type != ht_type_none)
167
return_error(gs_error_invalidaccess);
166
return_error(gs_error_invalidaccess);
169
168
phtc->type = ht_type_threshold;
170
169
phtc->params.ht_threshold.width = width;
202
201
rc_decrement_only(pht, "gs_ht_release");
207
205
* Verify that a gs_ht halftone is legitimate.
215
213
int num_comps = pht->params.ht_multiple.num_comp;
217
215
if (pht->type != ht_type_multiple)
218
return_error(gs_error_unregistered);
216
return_error(gs_error_unregistered);
219
217
for (i = 0; i < num_comps; i++) {
220
gs_ht_component *phtc = &(pht->params.ht_multiple.components[i]);
221
if ((phtc->type != ht_type_spot) && (phtc->type != ht_type_threshold))
222
return_error(gs_error_unregistered);
218
gs_ht_component *phtc = &(pht->params.ht_multiple.components[i]);
219
if ((phtc->type != ht_type_spot) && (phtc->type != ht_type_threshold))
220
return_error(gs_error_unregistered);
239
237
frac *values = pmap->values;
241
239
if (phtc->type == ht_type_spot) {
242
proc = phtc->params.ht_spot.transfer_closure.proc;
243
client_info = phtc->params.ht_spot.transfer_closure.data;
240
proc = phtc->params.ht_spot.transfer_closure.proc;
241
client_info = phtc->params.ht_spot.transfer_closure.data;
245
proc = phtc->params.ht_threshold.transfer_closure.proc;
246
client_info = phtc->params.ht_threshold.transfer_closure.data;
243
proc = phtc->params.ht_threshold.transfer_closure.proc;
244
client_info = phtc->params.ht_threshold.transfer_closure.data;
249
247
for (i = 0; i < transfer_map_size; i++) {
251
proc(i * (1 / (double)(transfer_map_size - 1)), pmap, client_info);
249
proc(i * (1 / (double)(transfer_map_size - 1)), pmap, client_info);
254
(fval <= 0.0 ? frac_0 : fval >= 1.0 ? frac_1 :
252
(fval <= 0.0 ? frac_0 : fval >= 1.0 ? frac_1 :
264
262
static gx_ht_order_component *
271
269
int num_comps = pht->params.ht_multiple.num_comp;
272
270
gx_ht_order_component *pocs = gs_alloc_struct_array(
274
pht->params.ht_multiple.num_comp,
275
gx_ht_order_component,
276
&st_ht_order_component_element,
272
pht->params.ht_multiple.num_comp,
273
gx_ht_order_component,
274
&st_ht_order_component_element,
284
282
pocs->corder.transfer = 0;
286
284
for (i = 0; i < num_comps; i++) {
287
gs_ht_component *phtc = &(pht->params.ht_multiple.components[i]);
288
gx_transfer_map *pmap = gs_alloc_struct(pmem,
297
for (j = 0; j < inext; j++)
298
gs_free_object(pmem, pocs[j].corder.transfer, "alloc_ht_order");
299
gs_free_object(pmem, pocs, "alloc_ht_order");
302
pmap->proc = gs_mapped_transfer;
303
pmap->id = gs_next_ids(pmem, 1);
304
pocs[inext].corder.levels = 0;
305
pocs[inext].corder.bit_data = 0;
306
pocs[inext].corder.cache = 0;
307
pocs[inext].corder.transfer = pmap;
308
pocs[inext].cname = phtc->cname;
285
gs_ht_component *phtc = &(pht->params.ht_multiple.components[i]);
286
gx_transfer_map *pmap = gs_alloc_struct(pmem,
295
for (j = 0; j < inext; j++)
296
gs_free_object(pmem, pocs[j].corder.transfer, "alloc_ht_order");
297
gs_free_object(pmem, pocs, "alloc_ht_order");
300
pmap->proc = gs_mapped_transfer;
301
pmap->id = gs_next_ids(pmem, 1);
302
pocs[inext].corder.levels = 0;
303
pocs[inext].corder.bit_data = 0;
304
pocs[inext].corder.cache = 0;
305
pocs[inext].corder.transfer = pmap;
306
pocs[inext].cname = phtc->cname;
309
307
pocs[inext].comp_number = phtc->comp_number;
310
comp2order[i] = inext++;
308
comp2order[i] = inext++;
321
gs_ht_component * phtc,
322
gx_ht_order * porder,
319
gs_ht_component * phtc,
320
gx_ht_order * porder,
327
325
if (phtc->type == ht_type_spot) {
328
gs_screen_enum senum;
331
code = gx_ht_process_screen_memory(&senum,
333
&phtc->params.ht_spot.screen,
334
phtc->params.ht_spot.accurate_screens,
340
/* avoid wiping out the transfer structure pointer */
341
senum.order.transfer = porder->transfer;
342
*porder = senum.order;
326
gs_screen_enum senum;
329
code = gx_ht_process_screen_memory(&senum,
331
&phtc->params.ht_spot.screen,
332
phtc->params.ht_spot.accurate_screens,
338
/* avoid wiping out the transfer structure pointer */
339
senum.order.transfer = porder->transfer;
340
*porder = senum.order;
344
342
} else { /* ht_type_threshold */
346
gx_transfer_map *transfer = porder->transfer;
344
gx_transfer_map *transfer = porder->transfer;
348
porder->params.M = phtc->params.ht_threshold.width;
349
porder->params.N = 0;
350
porder->params.R = 1;
351
porder->params.M1 = phtc->params.ht_threshold.height;
352
porder->params.N1 = 0;
353
porder->params.R1 = 1;
354
code = gx_ht_alloc_threshold_order(porder,
355
phtc->params.ht_threshold.width,
356
phtc->params.ht_threshold.height,
362
gx_ht_construct_threshold_order(
364
phtc->params.ht_threshold.thresholds.data
367
* gx_ht_construct_threshold_order wipes out transfer map pointer,
370
porder->transfer = transfer;
346
porder->params.M = phtc->params.ht_threshold.width;
347
porder->params.N = 0;
348
porder->params.R = 1;
349
porder->params.M1 = phtc->params.ht_threshold.height;
350
porder->params.N1 = 0;
351
porder->params.R1 = 1;
352
code = gx_ht_alloc_threshold_order(porder,
353
phtc->params.ht_threshold.width,
354
phtc->params.ht_threshold.height,
360
gx_ht_construct_threshold_order(
362
phtc->params.ht_threshold.thresholds.data
365
* gx_ht_construct_threshold_order wipes out transfer map pointer,
368
porder->transfer = transfer;
373
371
build_transfer_map(phtc, porder->transfer);
381
379
free_order_array(
382
gx_ht_order_component * pocs,
380
gx_ht_order_component * pocs,
389
387
for (i = 0; i < num_comps; i++)
390
gx_ht_order_release(&(pocs[i].corder), pmem, true);
388
gx_ht_order_release(&(pocs[i].corder), pmem, true);
391
389
gs_free_object(pmem, pocs, "gs_ht_install");
396
393
* Install a gs_ht halftone as the current halftone in the graphic state.
412
409
/* perform so sanity checks (must have one default component) */
413
410
if ((code = check_ht(pht)) != 0)
416
413
/* allocate the halftone order structure and transfer maps */
417
414
if ((pocs = alloc_ht_order(pht, pmem, comp2order)) == 0)
418
return_error(gs_error_VMerror);
415
return_error(gs_error_VMerror);
420
417
/* build all of the order for each component */
421
418
for (i = 0; i < num_comps; i++) {
422
int j = comp2order[i];
424
code = build_component(&(pht->params.ht_multiple.components[i]),
430
if ((code >= 0) && (j != 0)) {
433
pcache = gx_ht_alloc_cache(pmem,
435
pocs[j].corder.raster *
436
(pocs[j].corder.num_bits /
437
pocs[j].corder.width) * 4
441
code = gs_note_error(gs_error_VMerror);
443
pocs[j].corder.cache = pcache;
444
gx_ht_init_cache(pmem, pcache, &(pocs[j].corder));
419
int j = comp2order[i];
421
code = build_component(&(pht->params.ht_multiple.components[i]),
427
if ((code >= 0) && (j != 0)) {
430
pcache = gx_ht_alloc_cache(pmem,
432
pocs[j].corder.raster *
433
(pocs[j].corder.num_bits /
434
pocs[j].corder.width) * 4
438
code = gs_note_error(gs_error_VMerror);
440
pocs[j].corder.cache = pcache;
441
gx_ht_init_cache(pmem, pcache, &(pocs[j].corder));
452
free_order_array(pocs, num_comps, pmem);
449
free_order_array(pocs, num_comps, pmem);
455
452
/* initialize the device halftone structure */
456
453
dev_ht.rc.memory = pmem;
457
454
dev_ht.order = pocs[0].corder; /* Default */
458
455
if (num_comps == 1) {
459
/* we have only a Default; we don't need components. */
460
gs_free_object(pmem, pocs, "gs_ht_install");
461
dev_ht.components = 0;
456
/* we have only a Default; we don't need components. */
457
gs_free_object(pmem, pocs, "gs_ht_install");
458
dev_ht.components = 0;
463
dev_ht.components = pocs;
464
dev_ht.num_comp = num_comps;
460
dev_ht.components = pocs;
461
dev_ht.num_comp = num_comps;
467
464
/* at last, actually install the halftone in the graphic state */
481
478
create_mask_bits(const byte * mask1, const byte * mask2,
482
int width, int height, gx_ht_bit * bits)
479
int width, int height, gx_ht_bit * bits)
485
482
* We do this with the slowest, simplest possible algorithm....
491
488
for (y = 0; y < height; ++y)
492
for (x = 0; x < width; ++x) {
493
int offset = y * width_bytes + (x >> 3);
494
byte bit_mask = 0x80 >> (x & 7);
489
for (x = 0; x < width; ++x) {
490
int offset = y * width_bytes + (x >> 3);
491
byte bit_mask = 0x80 >> (x & 7);
496
if ((mask1[offset] ^ mask2[offset]) & bit_mask) {
498
gx_ht_construct_bit(&bits[count], width, y * width + x);
493
if ((mask1[offset] ^ mask2[offset]) & bit_mask) {
495
gx_ht_construct_bit(&bits[count], width, y * width + x);
505
502
create_mask_order(gx_ht_order * porder, gs_state * pgs,
506
const gs_client_order_halftone * phcop,
503
const gs_client_order_halftone * phcop,
509
506
int width_bytes = (phcop->width + 7) >> 3;
510
507
const byte *masks = (const byte *)phcop->client_data;
518
515
/* Do a first pass to compute how many bits entries will be needed. */
519
516
for (prev_mask = masks, num_bits = 0, i = 0;
521
++i, prev_mask += bytes_per_mask
523
num_bits += create_mask_bits(prev_mask, prev_mask + bytes_per_mask,
524
phcop->width, phcop->height, NULL);
518
++i, prev_mask += bytes_per_mask
520
num_bits += create_mask_bits(prev_mask, prev_mask + bytes_per_mask,
521
phcop->width, phcop->height, NULL);
525
522
code = gx_ht_alloc_client_order(porder, phcop->width, phcop->height,
526
num_levels, num_bits, mem);
523
num_levels, num_bits, mem);
529
526
/* Fill in the bits and levels entries. */
530
527
for (prev_mask = masks, num_bits = 0, i = 0;
532
++i, prev_mask += bytes_per_mask
534
porder->levels[i] = num_bits;
535
num_bits += create_mask_bits(prev_mask, prev_mask + bytes_per_mask,
536
phcop->width, phcop->height,
537
((gx_ht_bit *)porder->bit_data) +
529
++i, prev_mask += bytes_per_mask
531
porder->levels[i] = num_bits;
532
num_bits += create_mask_bits(prev_mask, prev_mask + bytes_per_mask,
533
phcop->width, phcop->height,
534
((gx_ht_bit *)porder->bit_data) +
540
537
porder->levels[num_levels - 1] = num_bits;
556
553
gs_ht_set_mask_comp(gs_ht * pht,
558
int width, int height, int num_levels,
559
const byte * masks, /* width x height x num_levels bits */
560
gs_ht_transfer_proc transfer,
561
const void *client_data)
555
int width, int height, int num_levels,
556
const byte * masks, /* width x height x num_levels bits */
557
gs_ht_transfer_proc transfer,
558
const void *client_data)
563
560
gs_ht_component *phtc =
564
561
&(pht->params.ht_multiple.components[component_index]);
566
563
if (component_index >= pht->params.ht_multiple.num_comp)
567
return_error(gs_error_rangecheck);
564
return_error(gs_error_rangecheck);
568
565
if (phtc->type != ht_type_none)
569
return_error(gs_error_invalidaccess);
566
return_error(gs_error_invalidaccess);
571
568
phtc->type = ht_type_client_order;
572
569
phtc->params.client_order.width = width;
575
572
phtc->params.client_order.procs = &mask_order_procs;
576
573
phtc->params.client_order.client_data = masks;
577
574
phtc->params.client_order.transfer_closure.proc =
578
(transfer == 0 ? null_closure_transfer : transfer);
575
(transfer == 0 ? null_closure_transfer : transfer);
579
576
phtc->params.client_order.transfer_closure.data = client_data;