Commit | Line | Data |
---|---|---|
d361b0f9 WJ |
1 | /* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* zht.c */ | |
21 | /* Halftone operators and rendering for Ghostscript */ | |
22 | #include "ghost.h" | |
23 | #include "memory_.h" | |
24 | #include "errors.h" | |
25 | #include "oper.h" | |
26 | #include "alloc.h" | |
27 | #include "estack.h" | |
28 | #include "gsmatrix.h" | |
29 | #include "gsstate.h" | |
30 | #include "state.h" | |
31 | #include "store.h" | |
32 | ||
33 | /* Forward references */ | |
34 | private int screen_sample(P1(os_ptr)); | |
35 | private int set_screen_continue(P1(os_ptr)); | |
36 | private int i_set_screen_continue; | |
37 | ||
38 | /* currenthalftonephase */ | |
39 | int | |
40 | zcurrenthalftonephase(register os_ptr op) | |
41 | { gs_int_point phase; | |
42 | gs_currenthalftonephase(igs, &phase); | |
43 | push(2); | |
44 | make_int(op - 1, phase.x); | |
45 | make_int(op, phase.y); | |
46 | return 0; | |
47 | } | |
48 | ||
49 | /* currentscreen */ | |
50 | int | |
51 | zcurrentscreen(register os_ptr op) | |
52 | { float freq, angle; | |
53 | float (*proc)(P2(floatp, floatp)); | |
54 | gs_currentscreen(igs, &freq, &angle, &proc); | |
55 | push(3); | |
56 | make_real(op - 2, freq); | |
57 | make_real(op - 1, angle); | |
58 | *op = istate.screen_proc; | |
59 | return 0; | |
60 | } | |
61 | ||
62 | /* sethalftonephase */ | |
63 | int | |
64 | zsethalftonephase(register os_ptr op) | |
65 | { int code; | |
66 | long x, y; | |
67 | check_type(op[-1], t_integer); | |
68 | check_type(*op, t_integer); | |
69 | x = op[-1].value.intval; | |
70 | y = op->value.intval; | |
71 | if ( x != (int)x || y != (int)y ) | |
72 | return e_rangecheck; | |
73 | code = gs_sethalftonephase(igs, (int)x, (int)y); | |
74 | if ( code >= 0 ) pop(2); | |
75 | return code; | |
76 | } | |
77 | ||
78 | /* The setscreen operator is complex because it has to sample */ | |
79 | /* each pixel in the pattern cell, calling a procedure, and then */ | |
80 | /* sort the result into a whitening order. */ | |
81 | ||
82 | /* Layout of stuff pushed on estack: */ | |
83 | /* Control mark, */ | |
84 | /* spot procedure, */ | |
85 | /* enumeration structure (as bytes). */ | |
86 | #define snumpush 3 | |
87 | #define sproc esp[-1] | |
88 | #define senum (gs_screen_enum *)esp->value.bytes | |
89 | ||
90 | /* setscreen */ | |
91 | int | |
92 | zsetscreen(register os_ptr op) | |
93 | { float fa[2]; | |
94 | int code = num_params(op - 1, 2, fa); | |
95 | gs_screen_enum *penum; | |
96 | if ( code < 0 ) return code; | |
97 | check_proc(*op); | |
98 | penum = (gs_screen_enum *)alloc(1, gs_screen_enum_sizeof, "setscreen"); | |
99 | if ( penum == 0 ) return e_VMerror; | |
100 | code = gs_screen_init(penum, igs, fa[0], fa[1]); | |
101 | if ( code < 0 ) | |
102 | { alloc_free((char *)penum, 1, gs_screen_enum_sizeof, "setscreen"); | |
103 | return code; | |
104 | } | |
105 | /* Push everything on the estack */ | |
106 | check_estack(snumpush); | |
107 | mark_estack(es_other); | |
108 | *++esp = *op; /* sproc = proc */ | |
109 | ++esp; | |
110 | make_tasv(esp, t_string, 0, gs_screen_enum_sizeof, bytes, (byte *)penum); | |
111 | pop(3); op -= 3; | |
112 | return screen_sample(op); | |
113 | } | |
114 | /* Set up the next sample */ | |
115 | private int | |
116 | screen_sample(register os_ptr op) | |
117 | { gs_screen_enum *penum = senum; | |
118 | gs_point pt; | |
119 | int code = gs_screen_currentpoint(penum, &pt); | |
120 | ref proc; | |
121 | if ( code < 0 ) return code; | |
122 | if ( code != 0 ) | |
123 | { /* All done */ | |
124 | istate.screen_proc = sproc; | |
125 | esp -= snumpush; | |
126 | return o_pop_estack; | |
127 | } | |
128 | push(2); | |
129 | make_real(op - 1, pt.x); | |
130 | make_real(op, pt.y); | |
131 | proc = sproc; | |
132 | push_op_estack(set_screen_continue, i_set_screen_continue); | |
133 | *++esp = proc; | |
134 | return o_push_estack; | |
135 | } | |
136 | static int count_cont; | |
137 | /* Continuation procedure for processing sampled pixels. */ | |
138 | private int | |
139 | set_screen_continue(register os_ptr op) | |
140 | { float value; | |
141 | int code = num_params(op, 1, &value); | |
142 | if ( code < 0 ) return code; | |
143 | code = gs_screen_next(senum, value); | |
144 | if ( code < 0 ) return code; | |
145 | pop(1); op--; | |
146 | return screen_sample(op); | |
147 | } | |
148 | ||
149 | /* ------ Initialization procedure ------ */ | |
150 | ||
151 | op_def zht_op_defs[] = { | |
152 | {"0currenthalftonephase", zcurrenthalftonephase}, | |
153 | {"0currentscreen", zcurrentscreen}, | |
154 | {"2sethalftonephase", zsethalftonephase}, | |
155 | {"3setscreen", zsetscreen}, | |
156 | /* Internal operators */ | |
157 | {"1%set_screen_continue", set_screen_continue, &i_set_screen_continue}, | |
158 | op_def_end(0) | |
159 | }; |