386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / zmatrix.c
CommitLineData
1530e5b9
WJ
1/* Copyright (C) 1989, 1991 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* zmatrix.c */
21/* Matrix operators for Ghostscript */
22#include "ghost.h"
23#include "errors.h"
24#include "oper.h"
25#include "gsmatrix.h"
26#include "state.h"
27#include "gscoord.h"
28#include "store.h"
29
30/* Forward references */
31private int near common_transform(P3(os_ptr,
32 int (*)(P4(gs_state *, floatp, floatp, gs_point *)),
33 int (*)(P4(floatp, floatp, const gs_matrix *, gs_point *))));
34
35/* Initialize the type and attributes of the identity matrix. */
36/* We may have to do this after each save and restore, */
37/* in order to get the l_new attribute correct. */
38void
39init_identity_matrix()
40{ extern gs_matrix gs_identity_matrix;
41 ref *mp = (ref *)&gs_identity_matrix;
42 int attrs = alloc_save_new_mask;
43 int i;
44 for ( i = 0; i < 6; i++, mp++ )
45 r_set_type_attrs(mp, t_real, attrs);
46}
47
48/* currentmatrix */
49int
50zcurrentmatrix(register os_ptr op)
51{ int code = write_matrix(op);
52 if ( code < 0 ) return code;
53 gs_currentmatrix(igs, (gs_matrix *)(op->value.refs));
54 return 0;
55}
56
57/* setmatrix */
58int
59zsetmatrix(register os_ptr op)
60{ gs_matrix mat;
61 int code = read_matrix(op, &mat);
62 if ( code < 0 ) return code;
63 if ( (code = gs_setmatrix(igs, &mat)) < 0 ) return code;
64 pop(1);
65 return 0;
66}
67
68/* translate */
69int
70ztranslate(register os_ptr op)
71{ int code = write_matrix(op);
72 float trans[2];
73 if ( code < 0 ) /* no matrix operand */
74 { if ( (code = num_params(op, 2, trans)) < 0 ) return code;
75 code = gs_translate(igs, trans[0], trans[1]);
76 }
77 else /* matrix operand */
78 { gs_matrix *pmat = (gs_matrix *)op->value.refs;
79 if ( (code = num_params(op - 1, 2, trans)) < 0 ) return code;
80 code = gs_make_translation(trans[0], trans[1], pmat);
81 op[-2] = *op;
82 }
83 if ( code >= 0 ) pop(2);
84 return code;
85}
86
87/* scale */
88int
89zscale(register os_ptr op)
90{ float scale[2];
91 int code = write_matrix(op);
92 if ( code < 0 ) /* no matrix operand */
93 { if ( (code = num_params(op, 2, scale)) < 0 ) return code;
94 code = gs_scale(igs, scale[0], scale[1]);
95 }
96 else /* matrix operand */
97 { gs_matrix *pmat = (gs_matrix *)op->value.refs;
98 if ( (code = num_params(op - 1, 2, scale)) < 0 ) return code;
99 code = gs_make_scaling(scale[0], scale[1], pmat);
100 op[-2] = *op;
101 }
102 if ( code >= 0 ) pop(2);
103 return code;
104}
105
106/* rotate */
107int
108zrotate(register os_ptr op)
109{ int code = write_matrix(op);
110 float ang;
111 if ( code < 0 ) /* no matrix operand */
112 { if ( (code = num_params(op, 1, &ang)) < 0 ) return code;
113 code = gs_rotate(igs, ang);
114 }
115 else /* matrix operand */
116 { gs_matrix *pmat = (gs_matrix *)op->value.refs;
117 if ( (code = num_params(op - 1, 1, &ang)) < 0 ) return code;
118 code = gs_make_rotation(ang, pmat);
119 op[-1] = *op;
120 }
121 if ( code >= 0 ) pop(1);
122 return code;
123}
124
125/* concat */
126int
127zconcat(register os_ptr op)
128{ gs_matrix mat;
129 int code = read_matrix(op, &mat);
130 if ( code < 0 ) return code;
131 code = gs_concat(igs, &mat);
132 if ( code < 0 ) return code;
133 pop(1);
134 return 0;
135}
136
137/* concatmatrix */
138int
139zconcatmatrix(register os_ptr op)
140{ gs_matrix m1, m2;
141 int code;
142 if ( (code = read_matrix(op - 2, &m1)) < 0 ||
143 (code = read_matrix(op - 1, &m2)) < 0 ||
144 (code = write_matrix(op)) < 0 ||
145 (code = gs_matrix_multiply(&m1, &m2, (gs_matrix *)(op->value.refs))) < 0
146 ) return code;
147 op[-2] = *op;
148 pop(2);
149 return code;
150}
151
152/* transform */
153int
154ztransform(register os_ptr op)
155{ return common_transform(op, gs_transform, gs_point_transform);
156}
157
158/* dtransform */
159int
160zdtransform(register os_ptr op)
161{ return common_transform(op, gs_dtransform, gs_distance_transform);
162}
163
164/* itransform */
165int
166zitransform(register os_ptr op)
167{ return common_transform(op, gs_itransform, gs_point_transform_inverse);
168}
169
170/* idtransform */
171int
172zidtransform(register os_ptr op)
173{ return common_transform(op, gs_idtransform, gs_distance_transform_inverse);
174}
175
176/* Common logic for [i][d]transform */
177private int near
178common_transform(register os_ptr op,
179 int (*ptproc)(P4(gs_state *, floatp, floatp, gs_point *)),
180 int (*matproc)(P4(floatp, floatp, const gs_matrix *, gs_point *)))
181{ float opxy[2];
182 gs_point pt;
183 int code;
184 /* Optimize for the non-matrix case */
185 switch ( r_type(op) )
186 {
187 case t_real: opxy[1] = op->value.realval; break;
188 case t_integer: opxy[1] = op->value.intval; break;
189 case t_array: /* might be a matrix */
190 { gs_matrix mat;
191 gs_matrix *pmat = &mat;
192 if ( (code = read_matrix(op, pmat)) < 0 ||
193 (code = num_params(op - 1, 2, opxy)) < 0 ||
194 (code = (*matproc)(opxy[0], opxy[1], pmat, &pt)) < 0
195 ) return code;
196 op--;
197 pop(1);
198 goto out;
199 }
200 default: return e_typecheck;
201 }
202 switch ( r_type(op - 1) )
203 {
204 case t_real: opxy[0] = (op - 1)->value.realval; break;
205 case t_integer: opxy[0] = (op - 1)->value.intval; break;
206 default: return e_typecheck;
207 }
208 if ( (code = (*ptproc)(igs, opxy[0], opxy[1], &pt)) < 0 )
209 return code;
210out: make_real(op - 1, pt.x);
211 make_real(op, pt.y);
212 return 0;
213}
214
215/* invertmatrix */
216int
217zinvertmatrix(register os_ptr op)
218{ gs_matrix m;
219 int code;
220 if ( (code = read_matrix(op - 1, &m)) < 0 ||
221 (code = write_matrix(op)) < 0 ||
222 (code = gs_matrix_invert(&m, (gs_matrix *)op->value.refs)) < 0
223 ) return code;
224 op[-1] = *op;
225 pop(1);
226 return code;
227}
228
229/* ------ Initialization procedure ------ */
230
231op_def zmatrix_op_defs[] = {
232 {"1concat", zconcat},
233 {"2dtransform", zdtransform},
234 {"3concatmatrix", zconcatmatrix},
235 {"1currentmatrix", zcurrentmatrix},
236 {"2idtransform", zidtransform},
237 {"2invertmatrix", zinvertmatrix},
238 {"2itransform", zitransform},
239 {"1rotate", zrotate},
240 {"2scale", zscale},
241 {"1setmatrix", zsetmatrix},
242 {"2transform", ztransform},
243 {"2translate", ztranslate},
244 op_def_end(init_identity_matrix)
245};