home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1991, 1993 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
- */
-
- /* zht.c */
- /* Halftone definition operators */
- #include "ghost.h"
- #include "memory_.h"
- #include "errors.h"
- #include "oper.h"
- #include "estack.h"
- #include "gsstruct.h" /* must precede igstate.h, */
- /* because of #ifdef in gsht.h */
- #include "ialloc.h"
- #include "igstate.h"
- #include "gsmatrix.h"
- #include "gxdevice.h" /* for gzht.h */
- #include "gzht.h"
- #include "gsstate.h"
- #include "store.h"
-
- /* Forward references */
- private int screen_params(P2(os_ptr, gs_screen_halftone *));
- private int screen_sample(P1(os_ptr));
- private int set_screen_continue(P1(os_ptr));
- private int screen_cleanup(P1(os_ptr));
-
- /* Dummy spot function */
- float
- spot_dummy(floatp x, floatp y)
- { return (x + y) / 2;
- }
-
- /* - .currenthalftone <dict> 0 */
- /* - .currenthalftone <frequency> <angle> <proc> 1 */
- /* - .currenthalftone <red_freq> ... <gray_proc> 2 */
- private int
- zcurrenthalftone(register os_ptr op)
- { gs_halftone ht;
- gs_currenthalftone(igs, &ht);
- switch ( ht.type )
- {
- case ht_type_screen:
- push(4);
- make_real(op - 3, ht.params.screen.frequency);
- make_real(op - 2, ht.params.screen.angle);
- op[-1] = istate->screen_procs.colored.gray;
- make_int(op, 1);
- break;
- case ht_type_colorscreen:
- push(13);
- { int i;
- for ( i = 0; i < 4; i++ )
- { os_ptr opc = op - 12 + i * 3;
- gs_screen_halftone *pht =
- &ht.params.colorscreen.screens.indexed[i];
- make_real(opc, pht->frequency);
- make_real(opc + 1, pht->angle);
- opc[2] = istate->screen_procs.indexed[i];
- }
- }
- make_int(op, 2);
- break;
- default: /* Screen was set by sethalftone. */
- push(2);
- op[-1] = istate->halftone;
- make_int(op, 0);
- break;
- }
- return 0;
- }
-
- /* The setscreen operator is complex because it has to sample */
- /* each pixel in the pattern cell, calling a procedure, and then */
- /* sort the result into a whitening order. */
-
- /* Layout of stuff pushed on estack: */
- /* Control mark, */
- /* [other stuff for other screen-setting operators], */
- /* finishing procedure, */
- /* spot procedure, */
- /* enumeration structure (as bytes). */
- #define snumpush 4
- #define sproc esp[-1]
- #define senum r_ptr(esp, gs_screen_enum)
-
- /* Forward references */
- int zsetscreen_init(P5(os_ptr, gs_screen_halftone *, ref *, int,
- int (*)(P1(os_ptr))));
- private int setscreen_finish(P1(os_ptr));
-
- /* <frequency> <angle> <proc> setscreen - */
- int
- zsetscreen(register os_ptr op)
- { gs_screen_halftone screen;
- int code = screen_params(op, &screen);
- if ( code < 0 )
- return code;
- return zsetscreen_init(op, &screen, op, 3, setscreen_finish);
- }
- /* We break out the body of this operator so it can be shared with */
- /* the code for Type 1 halftones in sethalftone. */
- int
- zsetscreen_init(os_ptr op, gs_screen_halftone *psp, ref *pproc,
- int npop, int (*finish_proc)(P1(os_ptr)))
- { gs_screen_enum *penum;
- int code;
- check_estack(snumpush + 1);
- penum = gs_screen_enum_alloc(imemory, "setscreen");
- if ( penum == 0 )
- return_error(e_VMerror);
- make_istruct(esp + snumpush, 0, penum); /* do early for screen_cleanup in case of error */
- code = gs_screen_init(penum, igs, psp);
- if ( code < 0 )
- { screen_cleanup(op);
- return code;
- }
- /* Push everything on the estack */
- make_mark_estack(esp + 1, es_other, screen_cleanup);
- esp += snumpush;
- make_op_estack(esp - 2, finish_proc);
- sproc = *pproc;
- push_op_estack(screen_sample);
- pop(npop);
- return o_push_estack;
- }
- /* Set up the next sample */
- private int
- screen_sample(register os_ptr op)
- { gs_screen_enum *penum = senum;
- gs_point pt;
- int code = gs_screen_currentpoint(penum, &pt);
- ref proc;
- switch ( code )
- {
- default:
- return code;
- case 1:
- /* All done */
- code = (*real_opproc(esp - 2))(op);
- esp -= snumpush;
- screen_cleanup(op);
- return (code < 0 ? code : o_pop_estack);
- case 0:
- ;
- }
- push(2);
- make_real(op - 1, pt.x);
- make_real(op, pt.y);
- proc = sproc;
- push_op_estack(set_screen_continue);
- *++esp = proc;
- return o_push_estack;
- }
- /* Continuation procedure for processing sampled pixels. */
- private int
- set_screen_continue(register os_ptr op)
- { float value;
- int code = num_params(op, 1, &value);
- if ( code < 0 ) return code;
- code = gs_screen_next(senum, value);
- if ( code < 0 ) return code;
- pop(1); op--;
- return screen_sample(op);
- }
- /* Finish setscreen. */
- private int
- setscreen_finish(os_ptr op)
- { gs_screen_install(senum);
- istate->screen_procs.colored.red = sproc;
- istate->screen_procs.colored.green = sproc;
- istate->screen_procs.colored.blue = sproc;
- istate->screen_procs.colored.gray = sproc;
- make_null(&istate->halftone);
- return 0;
- }
- /* Clean up after screen enumeration */
- private int
- screen_cleanup(os_ptr op)
- { ifree_object(esp[snumpush].value.pstruct, "screen_cleanup");
- return 0;
- }
-
- /* <red_freq> ... <gray_proc> setcolorscreen - */
- int spot_sample_finish(P1(os_ptr)); /* forward reference */
- private int setcolorscreen_finish(P1(os_ptr));
- private int setcolorscreen_cleanup(P1(os_ptr));
- /* The operator entry for setcolorscreen is in zcolor1.c, not here, */
- /* so we have to export the procedure. */
- int
- zsetcolorscreen(register os_ptr op)
- { gs_colorscreen_halftone cscreen;
- ref sprocs[4];
- gs_halftone *pht;
- gx_device_halftone *pdht;
- int i;
- int code = 0;
- for ( i = 0; i < 4; i++ )
- { os_ptr op1 = op - 9 + i * 3;
- int code = screen_params(op1, &cscreen.screens.indexed[i]);
- if ( code < 0 )
- return code;
- cscreen.screens.indexed[i].spot_function = spot_dummy;
- sprocs[i] = *op1;
- }
- check_estack(8); /* for sampling screens */
- pht = ialloc_struct(gs_halftone, &st_halftone, "setcolorscreen");
- pdht = ialloc_struct(gx_device_halftone, &st_device_halftone,
- "setcolorscreen");
- if ( pht == 0 || pdht == 0 )
- code = gs_note_error(e_VMerror);
- else
- { pht->type = ht_type_colorscreen;
- pht->params.colorscreen = cscreen;
- code = gs_sethalftone_prepare(igs, pht, pdht);
- }
- if ( code >= 0 )
- { /* Schedule the sampling of the screens. */
- es_ptr esp0 = esp; /* for backing out */
- esp += 8;
- make_mark_estack(esp - 7, es_other, setcolorscreen_cleanup);
- memcpy(esp - 6, sprocs, sizeof(ref) * 4); /* procs */
- make_istruct(esp - 2, 0, pht);
- make_istruct(esp - 1, 0, pdht);
- make_op_estack(esp, setcolorscreen_finish);
- for ( i = 0; i < 4; i++ )
- { code = zsetscreen_init(op,
- &cscreen.screens.indexed[i],
- &sprocs[i], 0, spot_sample_finish);
- if ( code < 0 )
- { esp = esp0;
- break;
- }
- /* Save the order index in the enumeration */
- /* structure, which is 1 below esp. */
- /* Shuffle the indices to correspond to */
- /* the component order. */
- { gs_screen_enum *penum =
- r_ptr(esp - 1, gs_screen_enum);
- penum->dev_ht = pdht;
- penum->comp_index = (i + 1) & 3;
- }
- }
- }
- if ( code < 0 )
- { ifree_object(pdht, "setcolorscreen");
- ifree_object(pht, "setcolorscreen");
- return code;
- }
- pop(12);
- return o_push_estack;
- }
- /* Finish the sampling of one screen. */
- /* This is exported for Type 1 sethalftone. */
- int
- spot_sample_finish(os_ptr op)
- { /* Copy the halftone order that was allocated by zsetscreen_init */
- /* to the one allocated by gs_sethalftone_prepare, */
- /* and free the former. */
- /* The enumeration structure is on top of the e-stack. */
- gs_screen_enum *penum = r_ptr(esp, gs_screen_enum);
- gx_device_halftone *pdht = penum->dev_ht;
- int ci = penum->comp_index;
- gx_ht_order *sorder = (pdht->components == 0 ?
- &pdht->order :
- &pdht->components[ci].corder);
- memcpy(sorder->levels, penum->order.levels,
- penum->order.num_levels * sizeof(uint));
- memcpy(sorder->bits, penum->order.bits,
- penum->order.num_bits * sizeof(gx_ht_bit));
- ifree_object(penum->order.bits, "spot_sample_finish(bits)");
- ifree_object(penum->order.levels, "spot_sample_finish(levels)");
- return 0;
- }
- /* Install the color screen after sampling. */
- private int
- setcolorscreen_finish(os_ptr op)
- { gx_device_halftone *pdht = r_ptr(esp, gx_device_halftone);
- int code;
- pdht->order = pdht->components[0].corder;
- code = gx_ht_install(igs, r_ptr(esp - 1, gs_halftone), pdht);
- if ( code < 0 )
- return code;
- memcpy(istate->screen_procs.indexed, esp - 5, sizeof(ref) * 4);
- make_null(&istate->halftone);
- esp -= 7;
- setcolorscreen_cleanup(op);
- return o_pop_estack;
- }
- /* Clean up after installing the color screen. */
- private int
- setcolorscreen_cleanup(os_ptr op)
- { ifree_object(esp[7].value.pstruct,
- "setcolorscreen_cleanup(device halftone)");
- ifree_object(esp[6].value.pstruct,
- "setcolorscreen_cleanup(halftone)");
- return 0;
- }
-
- /* ------ Utility procedures ------ */
-
- /* Get parameters for a single screen. */
- private int
- screen_params(os_ptr op, gs_screen_halftone *phs)
- { float fa[2];
- int code = num_params(op - 1, 2, fa);
- if ( code < 0 )
- return code;
- check_proc(*op);
- phs->frequency = fa[0];
- phs->angle = fa[1];
- return 0;
- }
-
- /* ------ Initialization procedure ------ */
-
- op_def zht_op_defs[] = {
- {"0.currenthalftone", zcurrenthalftone},
- {"3setscreen", zsetscreen},
- /*{"<setcolorscreen", zsetcolorscreen},*/ /* in zcolor1.c */
- /* Internal operators */
- {"0%screen_sample", screen_sample},
- {"1%set_screen_continue", set_screen_continue},
- {"0%spot_sample_finish", spot_sample_finish},
- {"0%setscreen_finish", setscreen_finish},
- {"0%setcolorscreen_finish", setcolorscreen_finish},
- op_def_end(0)
- };
-