1 /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /*$Id: gsht1.c,v 1.15 2004/08/04 19:36:12 stefan Exp $ */
18 /* Extended halftone operators for Ghostscript library */
19 #include "memory_.h"
20 #include "string_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsstruct.h"
24 #include "gsutil.h" /* for gs_next_ids */
25 #include "gzstate.h"
26 #include "gxdevice.h" /* for gzht.h */
27 #include "gzht.h"
28
29 #include "gxwts.h"
30 #include "gswts.h"
31
32 /* Imports from gscolor.c */
33 void load_transfer_map(gs_state *, gx_transfer_map *, floatp);
34
35 /* Forward declarations */
36 private int process_spot(gx_ht_order *, gs_state *,
37 gs_spot_halftone *, gs_memory_t *);
38 private int process_threshold(gx_ht_order *, gs_state *,
39 gs_threshold_halftone *, gs_memory_t *);
40 private int process_threshold2(gx_ht_order *, gs_state *,
41 gs_threshold2_halftone *, gs_memory_t *);
42 private int process_client_order(gx_ht_order *, gs_state *,
43 gs_client_order_halftone *, gs_memory_t *);
44 private int
45 gs_sethalftone_try_wts(gs_halftone *pht, gs_state *pgs,
46 gx_device_halftone *pdht);
47
48 /* Structure types */
49 public_st_halftone_component();
50 public_st_ht_component_element();
51
52 /* GC procedures */
53
54 private
55 ENUM_PTRS_WITH(halftone_component_enum_ptrs, gs_halftone_component *hptr) return 0;
56 case 0:
57 switch (hptr->type)
58 {
59 case ht_type_spot:
60 ENUM_RETURN((hptr->params.spot.transfer == 0 ?
61 hptr->params.spot.transfer_closure.data :
62 0));
63 case ht_type_threshold:
64 ENUM_RETURN_CONST_STRING_PTR(gs_halftone_component,
65 params.threshold.thresholds);
66 case ht_type_threshold2:
67 return ENUM_CONST_BYTESTRING(&hptr->params.threshold2.thresholds);
68 case ht_type_client_order:
69 ENUM_RETURN(hptr->params.client_order.client_data);
70 default: /* not possible */
71 return 0;
72 }
73 case 1:
74 switch (hptr->type) {
75 case ht_type_threshold:
76 ENUM_RETURN((hptr->params.threshold.transfer == 0 ?
77 hptr->params.threshold.transfer_closure.data :
78 0));
79 case ht_type_threshold2:
80 ENUM_RETURN(hptr->params.threshold2.transfer_closure.data);
81 case ht_type_client_order:
82 ENUM_RETURN(hptr->params.client_order.transfer_closure.data);
83 default:
84 return 0;
85 }
86 ENUM_PTRS_END
RELOC_PTRS_WITH(halftone_component_reloc_ptrs,gs_halftone_component * hptr)87 private RELOC_PTRS_WITH(halftone_component_reloc_ptrs, gs_halftone_component *hptr)
88 {
89 switch (hptr->type) {
90 case ht_type_spot:
91 if (hptr->params.spot.transfer == 0)
92 RELOC_VAR(hptr->params.spot.transfer_closure.data);
93 break;
94 case ht_type_threshold:
95 RELOC_CONST_STRING_VAR(hptr->params.threshold.thresholds);
96 if (hptr->params.threshold.transfer == 0)
97 RELOC_VAR(hptr->params.threshold.transfer_closure.data);
98 break;
99 case ht_type_threshold2:
100 RELOC_CONST_BYTESTRING_VAR(hptr->params.threshold2.thresholds);
101 RELOC_OBJ_VAR(hptr->params.threshold2.transfer_closure.data);
102 break;
103 case ht_type_client_order:
104 RELOC_VAR(hptr->params.client_order.client_data);
105 RELOC_VAR(hptr->params.client_order.transfer_closure.data);
106 break;
107 default:
108 break;
109 }
110 }
111 RELOC_PTRS_END
112
113 /* setcolorscreen */
114 int
gs_setcolorscreen(gs_state * pgs,gs_colorscreen_halftone * pht)115 gs_setcolorscreen(gs_state * pgs, gs_colorscreen_halftone * pht)
116 {
117 gs_halftone ht;
118
119 ht.type = ht_type_colorscreen;
120 ht.params.colorscreen = *pht;
121 return gs_sethalftone(pgs, &ht);
122 }
123
124 /* currentcolorscreen */
125 int
gs_currentcolorscreen(gs_state * pgs,gs_colorscreen_halftone * pht)126 gs_currentcolorscreen(gs_state * pgs, gs_colorscreen_halftone * pht)
127 {
128 int code;
129
130 switch (pgs->halftone->type) {
131 case ht_type_colorscreen:
132 *pht = pgs->halftone->params.colorscreen;
133 return 0;
134 default:
135 code = gs_currentscreen(pgs, &pht->screens.colored.gray);
136 if (code < 0)
137 return code;
138 pht->screens.colored.red = pht->screens.colored.gray;
139 pht->screens.colored.green = pht->screens.colored.gray;
140 pht->screens.colored.blue = pht->screens.colored.gray;
141 return 0;
142 }
143 }
144
145 /* Set the halftone in the graphics state. */
146 int
gs_sethalftone(gs_state * pgs,gs_halftone * pht)147 gs_sethalftone(gs_state * pgs, gs_halftone * pht)
148 {
149 gs_halftone ht;
150
151 ht = *pht;
152 ht.rc.memory = pgs->memory;
153 return gs_sethalftone_allocated(pgs, &ht);
154 }
155 int
gs_sethalftone_allocated(gs_state * pgs,gs_halftone * pht)156 gs_sethalftone_allocated(gs_state * pgs, gs_halftone * pht)
157 {
158 gx_device_halftone dev_ht;
159 int code = gs_sethalftone_prepare(pgs, pht, &dev_ht);
160
161 if (code < 0)
162 return code;
163 dev_ht.rc.memory = pht->rc.memory;
164 if ((code = gx_ht_install(pgs, pht, &dev_ht)) < 0)
165 gx_device_halftone_release(&dev_ht, pht->rc.memory);
166 return code;
167 }
168
169 /* Prepare the halftone, but don't install it. */
170 int
gs_sethalftone_prepare(gs_state * pgs,gs_halftone * pht,gx_device_halftone * pdht)171 gs_sethalftone_prepare(gs_state * pgs, gs_halftone * pht,
172 gx_device_halftone * pdht)
173 {
174 gs_memory_t *mem = pht->rc.memory;
175 gx_ht_order_component *pocs = 0;
176 int code = 0;
177
178 if (gs_currentusewts() && gs_sethalftone_try_wts(pht, pgs, pdht) == 0)
179 return 0;
180
181 switch (pht->type) {
182 case ht_type_colorscreen:
183 {
184 gs_screen_halftone *phc =
185 pht->params.colorscreen.screens.indexed;
186 static const int cindex[4] = {3, 0, 1, 2};
187 static const char * color_names[4] = {"Gray", "Red", "Green", "Blue"};
188 int i;
189
190 pocs = gs_alloc_struct_array(mem, 4,
191 gx_ht_order_component,
192 &st_ht_order_component_element,
193 "gs_sethalftone");
194 if (pocs == 0)
195 return_error(gs_error_VMerror);
196 for (i = 0; i < 4; i++) {
197 gs_screen_enum senum;
198 int ci = cindex[i];
199 gx_ht_order_component *poc = &pocs[i];
200
201 code = gx_ht_process_screen_memory(&senum, pgs,
202 &phc[ci], gs_currentaccuratescreens(), mem);
203 if (code < 0)
204 break;
205 poc->corder = senum.order;
206 poc->comp_number = gs_color_name_component_number(pgs->device,
207 color_names[i], strlen(color_names[i]), pht->type);
208 poc->cname = 0; /* name index values are not known (or needed) */
209 if (i == 0) /* Gray = Default */
210 pdht->order = poc->corder; /* Save default value */
211 }
212 if (code < 0)
213 break;
214 pdht->components = pocs;
215 pdht->num_comp = 4;
216 }
217 break;
218 case ht_type_spot:
219 code = process_spot(&pdht->order, pgs, &pht->params.spot, mem);
220 if (code < 0)
221 return code;
222 pdht->components = 0;
223 break;
224 case ht_type_threshold:
225 code = process_threshold(&pdht->order, pgs,
226 &pht->params.threshold, mem);
227 if (code < 0)
228 return code;
229 pdht->components = 0;
230 break;
231 case ht_type_threshold2:
232 code = process_threshold2(&pdht->order, pgs,
233 &pht->params.threshold2, mem);
234 if (code < 0)
235 return code;
236 pdht->components = 0;
237 break;
238 case ht_type_client_order:
239 code = process_client_order(&pdht->order, pgs,
240 &pht->params.client_order, mem);
241 if (code < 0)
242 return code;
243 pdht->components = 0;
244 break;
245 case ht_type_multiple:
246 case ht_type_multiple_colorscreen:
247 {
248 uint count = pht->params.multiple.num_comp;
249 bool have_Default = false;
250 uint i;
251 gs_halftone_component *phc = pht->params.multiple.components;
252 gx_ht_order_component *poc_next;
253
254 pocs = gs_alloc_struct_array(mem, count,
255 gx_ht_order_component,
256 &st_ht_order_component_element,
257 "gs_sethalftone");
258 if (pocs == 0)
259 return_error(gs_error_VMerror);
260 poc_next = pocs + 1;
261 for (i = 0; i < count; i++, phc++) {
262 gx_ht_order_component *poc = poc_next;
263
264 if (phc->comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
265 if (have_Default) {
266 /* Duplicate Default */
267 code = gs_note_error(gs_error_rangecheck);
268 break;
269 }
270 poc = pocs;
271 have_Default = true;
272 } else if (i == count - 1 && !have_Default) {
273 /* No Default */
274 code = gs_note_error(gs_error_rangecheck);
275 break;
276 } else
277 poc = poc_next++;
278
279 poc->comp_number = phc->comp_number;
280 poc->cname = phc->cname;
281 switch (phc->type) {
282 case ht_type_spot:
283 code = process_spot(&poc->corder, pgs,
284 &phc->params.spot, mem);
285 break;
286 case ht_type_threshold:
287 code = process_threshold(&poc->corder, pgs,
288 &phc->params.threshold, mem);
289 break;
290 case ht_type_threshold2:
291 code = process_threshold2(&poc->corder, pgs,
292 &phc->params.threshold2, mem);
293 break;
294 case ht_type_client_order:
295 code = process_client_order(&poc->corder, pgs,
296 &phc->params.client_order, mem);
297 break;
298 default:
299 code = gs_note_error(gs_error_rangecheck);
300 break;
301 }
302 if (code < 0)
303 break;
304 }
305 if (code < 0)
306 break;
307 pdht->order = pocs[0].corder; /* Default */
308 if (count == 1) {
309 /* We have only a Default; */
310 /* we don't need components. */
311 gs_free_object(mem, pocs, "gs_sethalftone");
312 pdht->components = 0;
313 pdht->num_comp = 0;
314 } else {
315 pdht->components = pocs;
316 pdht->num_comp = count;
317 }
318 }
319 break;
320 default:
321 return_error(gs_error_rangecheck);
322 }
323 if (code < 0)
324 gs_free_object(mem, pocs, "gs_sethalftone");
325 return code;
326 }
327
328 /* ------ Internal routines ------ */
329
330 /* Process a transfer function override, if any. */
331 private int
process_transfer(gx_ht_order * porder,gs_state * pgs,gs_mapping_proc proc,gs_mapping_closure_t * pmc,gs_memory_t * mem)332 process_transfer(gx_ht_order * porder, gs_state * pgs,
333 gs_mapping_proc proc, gs_mapping_closure_t * pmc,
334 gs_memory_t * mem)
335 {
336 gx_transfer_map *pmap;
337
338 if (proc == 0 && pmc->proc == 0)
339 return 0;
340 /*
341 * The transfer funtion is referenced by the order, so start the
342 * reference count at 1.
343 */
344 rc_alloc_struct_1(pmap, gx_transfer_map, &st_transfer_map, mem,
345 return_error(gs_error_VMerror),
346 "process_transfer");
347 pmap->proc = proc; /* 0 => use closure */
348 pmap->closure = *pmc;
349 pmap->id = gs_next_ids(mem, 1);
350 load_transfer_map(pgs, pmap, 0.0);
351 porder->transfer = pmap;
352 return 0;
353 }
354
355 /* Process a spot plane. */
356 private int
process_spot(gx_ht_order * porder,gs_state * pgs,gs_spot_halftone * phsp,gs_memory_t * mem)357 process_spot(gx_ht_order * porder, gs_state * pgs,
358 gs_spot_halftone * phsp, gs_memory_t * mem)
359 {
360 gs_screen_enum senum;
361
362 int code = gx_ht_process_screen_memory(&senum, pgs, &phsp->screen,
363 phsp->accurate_screens, mem);
364
365 if (code < 0)
366 return code;
367 *porder = senum.order;
368 return process_transfer(porder, pgs, phsp->transfer,
369 &phsp->transfer_closure, mem);
370 }
371
372 /* Construct the halftone order from a threshold array. */
373 void
gx_ht_complete_threshold_order(gx_ht_order * porder)374 gx_ht_complete_threshold_order(gx_ht_order * porder)
375 {
376 int num_levels = porder->num_levels;
377 uint *levels = porder->levels;
378 uint size = porder->num_bits;
379 gx_ht_bit *bits = porder->bit_data;
380 uint i, j;
381
382 /* The caller has set bits[i] = max(1, thresholds[i]). */
383 gx_sort_ht_order(bits, size);
384 /* We want to set levels[j] to the lowest value of i */
385 /* such that bits[i].mask > j. */
386 for (i = 0, j = 0; i < size; i++) {
387 if (bits[i].mask != j) {
388 if_debug3('h', "[h]levels[%u..%u] = %u\n",
389 j, (uint) bits[i].mask, i);
390 while (j < bits[i].mask)
391 levels[j++] = i;
392 }
393 }
394 while (j < num_levels)
395 levels[j++] = size;
396 gx_ht_construct_bits(porder);
397 }
398 int
gx_ht_construct_threshold_order(gx_ht_order * porder,const byte * thresholds)399 gx_ht_construct_threshold_order(gx_ht_order * porder, const byte * thresholds)
400 {
401 return porder->procs->construct_order(porder, thresholds);
402 }
403
404 /* Process a threshold plane. */
405 private int
process_threshold(gx_ht_order * porder,gs_state * pgs,gs_threshold_halftone * phtp,gs_memory_t * mem)406 process_threshold(gx_ht_order * porder, gs_state * pgs,
407 gs_threshold_halftone * phtp, gs_memory_t * mem)
408 {
409 int code;
410
411 porder->params.M = phtp->width, porder->params.N = 0;
412 porder->params.R = 1;
413 porder->params.M1 = phtp->height, porder->params.N1 = 0;
414 porder->params.R1 = 1;
415 code = gx_ht_alloc_threshold_order(porder, phtp->width, phtp->height,
416 256, mem);
417 if (code < 0)
418 return code;
419 gx_ht_construct_threshold_order(porder, phtp->thresholds.data);
420 return process_transfer(porder, pgs, phtp->transfer,
421 &phtp->transfer_closure, mem);
422 }
423
424 /* Process an extended threshold plane. */
425 private int
process_threshold2(gx_ht_order * porder,gs_state * pgs,gs_threshold2_halftone * phtp,gs_memory_t * mem)426 process_threshold2(gx_ht_order * porder, gs_state * pgs,
427 gs_threshold2_halftone * phtp, gs_memory_t * mem)
428 {
429 int code;
430 /*
431 * There are potentially 64K different levels for this plane, but this
432 * is more than we're willing to handle. Try to reduce the number of
433 * levels by dropping leading or trailing zero bits from the thresholds;
434 * as a last resort, drop (possibly significant) trailing bits.
435 */
436 #define LOG2_MAX_HT_LEVELS 14
437 #define MAX_HT_LEVELS (1 << LOG2_MAX_HT_LEVELS)
438 int bps = phtp->bytes_per_sample;
439 const byte *data = phtp->thresholds.data;
440 const int w1 = phtp->width, h1 = phtp->height, size1 = w1 * h1;
441 const int w2 = phtp->width2, h2 = phtp->height2, size2 = w2 * h2;
442 const uint size = size1 + size2;
443 const int d = (h2 == 0 ? h1 : igcd(h1, h2));
444 const int sod = size / d;
445 uint num_levels;
446 uint i;
447 int rshift = 0;
448 int shift;
449
450 {
451 uint mask = 0, max_thr = 0;
452
453 for (i = 0; i < size; ++i) {
454 uint thr =
455 (bps == 1 ? data[i] : (data[i * 2] << 8) + data[i * 2 + 1]);
456
457 mask |= thr;
458 max_thr = max(max_thr, thr);
459 }
460 if (mask == 0)
461 mask = 1, max_thr = 1;
462 while (!(mask & 1) || max_thr > MAX_HT_LEVELS)
463 mask >>= 1, max_thr >>= 1, rshift++;
464 num_levels = max_thr + 1;
465 }
466 /*
467 * Set nominal values for the params, and don't bother to call
468 * gx_compute_cell_values -- the values are only needed for spot
469 * halftones.
470 */
471 porder->params.M = sod, porder->params.N = d;
472 porder->params.R = 1;
473 porder->params.M1 = d, porder->params.N1 = sod;
474 porder->params.R1 = 1;
475 /*
476 * Determine the shift between strips. We don't know a closed formula
477 * for this, so we do it by enumeration.
478 */
479 shift = 0;
480 {
481 int x = 0, y = 0;
482
483 do {
484 if (y < h1)
485 x += w1, y += h2;
486 else
487 x += w2, y -= h1;
488 } while (y > d);
489 if (y)
490 shift = x;
491 }
492 code = gx_ht_alloc_ht_order(porder, sod, d, num_levels, size, shift,
493 &ht_order_procs_default, mem);
494 if (code < 0)
495 return code;
496 {
497 gx_ht_bit *bits = (gx_ht_bit *)porder->bit_data;
498 int row, di;
499
500 if_debug7('h', "[h]rect1=(%d,%d), rect2=(%d,%d), strip=(%d,%d), shift=%d\n",
501 w1, h1, w2, h2, sod, d, shift);
502 for (row = 0, di = 0; row < d; ++row) {
503 /* Iterate over destination rows. */
504 int dx, sy = row; /* sy = row mod d */
505 int w;
506
507 for (dx = 0; dx < sod; dx += w) {
508 /* Iterate within a destination row, over source rows. */
509 int si, j;
510
511 if (sy < h1) {
512 /* Copy a row from rect1. */
513 si = sy * w1;
514 w = w1;
515 sy += h2;
516 } else {
517 /* Copy a row from rect2. */
518 si = size1 + (sy - h1) * w2;
519 w = w2;
520 sy -= h1;
521 }
522 for (j = 0; j < w; ++j, ++si, ++di) {
523 uint thr =
524 (bps == 1 ? data[si] :
525 (data[si * 2] << 8) + data[si * 2 + 1])
526 >> rshift;
527
528 if_debug3('H', "[H]sy=%d, si=%d, di=%d\n", sy, si, di);
529 bits[di].mask = max(thr, 1);
530 }
531 }
532 }
533 }
534 gx_ht_complete_threshold_order(porder);
535 return process_transfer(porder, pgs, NULL, &phtp->transfer_closure, mem);
536 #undef LOG2_MAX_HT_LEVELS
537 #undef MAX_HT_LEVELS
538 }
539
540 /* Process a client-order plane. */
541 private int
process_client_order(gx_ht_order * porder,gs_state * pgs,gs_client_order_halftone * phcop,gs_memory_t * mem)542 process_client_order(gx_ht_order * porder, gs_state * pgs,
543 gs_client_order_halftone * phcop, gs_memory_t * mem)
544 {
545 int code = (*phcop->procs->create_order) (porder, pgs, phcop, mem);
546
547 if (code < 0)
548 return code;
549 return process_transfer(porder, pgs, NULL,
550 &phcop->transfer_closure, mem);
551 }
552
553 private const gx_ht_order_procs_t wts_order_procs = { 0
554 };
555
556 /**
557 * gs_sethalftone_try_wts: Try creating a wts-based device halftone.
558 * @pht: Client halftone.
559 * @pdht: Device halftone to initialize.
560 *
561 * Tries initializing @pdht based on data from @pht, using WTS.
562 *
563 * Return value: 0 on success, 1 to indicate that the initialization
564 * was not done, and that the legacy initialization code path should
565 * be used.
566 **/
567 private int
gs_sethalftone_try_wts(gs_halftone * pht,gs_state * pgs,gx_device_halftone * pdht)568 gs_sethalftone_try_wts(gs_halftone *pht, gs_state *pgs,
569 gx_device_halftone *pdht)
570 {
571 gx_device *dev = pgs->device;
572 int num_comps = dev->color_info.num_components;
573 int depth = dev->color_info.depth;
574
575 if (pht->type != ht_type_multiple)
576 /* Only work with Type 5 halftones. todo: we probably want
577 to relax this. */
578 return 1;
579
580 if_debug2('h', "[h]%s, num_comp = %d\n",
581 dev->color_info.separable_and_linear == GX_CINFO_SEP_LIN ? "Separable and linear" : "Not separable and linear!",
582 pht->params.multiple.num_comp);
583
584 if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN &&
585 pht->params.multiple.num_comp > 1)
586 /* WTS is only enabled for separable or monochrome devices. */
587 return 1;
588
589 /* only work with bilevel (not multilevel) devices */
590 if (depth > num_comps) {
591 if (depth >= 2 * num_comps)
592 return 1;
593 if (dev->color_info.gray_index != GX_CINFO_COMP_NO_INDEX &&
594 (dev->color_info.max_gray > 1 ||
595 (num_comps > 1 && dev->color_info.max_color > 1)))
596 return 1;
597 }
598
599 if (pht->type == ht_type_multiple) {
600 gs_halftone_component *components = pht->params.multiple.components;
601 uint num_comp = pht->params.multiple.num_comp;
602 int i;
603 gx_ht_order_component *pocs;
604 gx_ht_order_component *poc_next;
605 int code = 0;
606 bool have_Default = false;
607
608 for (i = 0; i < num_comp; i++) {
609 if (components[i].type != ht_type_spot)
610 return 1;
611 else {
612 gs_spot_halftone *spot = &components[i].params.spot;
613 if (!spot->accurate_screens)
614 return 1;
615 }
616 }
617
618 pocs = gs_alloc_struct_array( pgs->memory,
619 num_comp,
620 gx_ht_order_component,
621 &st_ht_order_component_element,
622 "gs_sethalftone_try_wts" );
623 /* pocs = malloc(num_comp * sizeof(gx_ht_order_component)); */
624 poc_next = &pocs[1];
625 for (i = 0; i < num_comp; i++) {
626 gs_halftone_component *component = &components[i];
627 gs_spot_halftone *spot = &component->params.spot;
628 gs_screen_halftone *h = &spot->screen;
629 gx_wts_cell_params_t *wcp;
630 gs_wts_screen_enum_t *wse;
631 gs_matrix imat;
632 gx_ht_order_component *poc;
633
634 if (component->comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
635 if (have_Default) {
636 /* Duplicate Default */
637 code = gs_note_error(gs_error_rangecheck);
638 break;
639 }
640 poc = pocs;
641 have_Default = true;
642 } else if (i == num_comp - 1 && !have_Default) {
643 /* No Default */
644 code = gs_note_error(gs_error_rangecheck);
645 break;
646 } else
647 poc = poc_next++;
648
649 gs_deviceinitialmatrix(gs_currentdevice(pgs), &imat);
650
651 wcp = wts_pick_cell_size(h, &imat);
652 wse = gs_wts_screen_enum_new(wcp);
653
654 poc->corder.wse = wse;
655 poc->corder.wts = NULL;
656 poc->corder.procs = &wts_order_procs;
657 poc->corder.data_memory = NULL;
658 poc->corder.num_levels = 0;
659 poc->corder.num_bits = 0;
660 poc->corder.levels = NULL;
661 poc->corder.bit_data = NULL;
662 poc->corder.cache = NULL;
663 poc->corder.transfer = NULL;
664 poc->comp_number = component->comp_number;
665 poc->cname = component->cname;
666 code = process_transfer( &poc->corder,
667 pgs,
668 spot->transfer,
669 &spot->transfer_closure,
670 pgs->memory );
671 if (code < 0)
672 break;
673 }
674 /* todo: cleanup on error */
675 pdht->components = pocs;
676 pdht->num_comp = num_comp;
677 return code;
678 }
679 return 1;
680 }
681