Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 1995, 1997, 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: zmatrix.c,v 1.8 2004/08/04 19:36:13 stefan Exp $ */
18
/* Matrix operators */
19
#include "ghost.h"
20
#include "oper.h"
21
#include "igstate.h"
22
#include "gsmatrix.h"
23
#include "gscoord.h"
24
#include "store.h"
25
 
26
/* Forward references */
27
private int common_transform(i_ctx_t *,
28
		int (*)(gs_state *, floatp, floatp, gs_point *),
29
		int (*)(floatp, floatp, const gs_matrix *, gs_point *));
30
 
31
/* - initmatrix - */
32
private int
33
zinitmatrix(i_ctx_t *i_ctx_p)
34
{
35
    return gs_initmatrix(igs);
36
}
37
 
38
/* <matrix> defaultmatrix <matrix> */
39
private int
40
zdefaultmatrix(i_ctx_t *i_ctx_p)
41
{
42
    os_ptr op = osp;
43
    gs_matrix mat;
44
 
45
    gs_defaultmatrix(igs, &mat);
46
    return write_matrix(op, &mat);
47
}
48
 
49
/* - .currentmatrix <xx> <xy> <yx> <yy> <tx> <ty> */
50
private int
51
zcurrentmatrix(i_ctx_t *i_ctx_p)
52
{
53
    os_ptr op = osp;
54
    gs_matrix mat;
55
    int code = gs_currentmatrix(igs, &mat);
56
 
57
    if (code < 0)
58
	return code;
59
    push(6);
60
    code = make_floats(op - 5, &mat.xx, 6);
61
    if (code < 0)
62
	pop(6);
63
    return code;
64
}
65
 
66
/* <xx> <xy> <yx> <yy> <tx> <ty> .setmatrix - */
67
private int
68
zsetmatrix(i_ctx_t *i_ctx_p)
69
{
70
    os_ptr op = osp;
71
    gs_matrix mat;
72
    int code = float_params(op, 6, &mat.xx);
73
 
74
    if (code < 0)
75
	return code;
76
    if ((code = gs_setmatrix(igs, &mat)) < 0)
77
	return code;
78
    pop(6);
79
    return 0;
80
}
81
 
82
/* <matrix|null> .setdefaultmatrix - */
83
private int
84
zsetdefaultmatrix(i_ctx_t *i_ctx_p)
85
{
86
    os_ptr op = osp;
87
    int code;
88
 
89
    if (r_has_type(op, t_null))
90
	code = gs_setdefaultmatrix(igs, NULL);
91
    else {
92
	gs_matrix mat;
93
 
94
	code = read_matrix(imemory, op, &mat);
95
	if (code < 0)
96
	    return code;
97
	code = gs_setdefaultmatrix(igs, &mat);
98
    }
99
    if (code < 0)
100
	return code;
101
    pop(1);
102
    return 0;
103
}
104
 
105
/* <tx> <ty> translate - */
106
/* <tx> <ty> <matrix> translate <matrix> */
107
private int
108
ztranslate(i_ctx_t *i_ctx_p)
109
{
110
    os_ptr op = osp;
111
    int code;
112
    double trans[2];
113
 
114
    if ((code = num_params(op, 2, trans)) >= 0) {
115
	code = gs_translate(igs, trans[0], trans[1]);
116
	if (code < 0)
117
	    return code;
118
    } else {			/* matrix operand */
119
	gs_matrix mat;
120
 
121
	/* The num_params failure might be a stack underflow. */
122
	check_op(2);
123
	if ((code = num_params(op - 1, 2, trans)) < 0 ||
124
	    (code = gs_make_translation(trans[0], trans[1], &mat)) < 0 ||
125
	    (code = write_matrix(op, &mat)) < 0
126
	    ) {			/* Might be a stack underflow. */
127
	    check_op(3);
128
	    return code;
129
	}
130
	op[-2] = *op;
131
    }
132
    pop(2);
133
    return code;
134
}
135
 
136
/* <sx> <sy> scale - */
137
/* <sx> <sy> <matrix> scale <matrix> */
138
private int
139
zscale(i_ctx_t *i_ctx_p)
140
{
141
    os_ptr op = osp;
142
    int code;
143
    double scale[2];
144
 
145
    if ((code = num_params(op, 2, scale)) >= 0) {
146
	code = gs_scale(igs, scale[0], scale[1]);
147
	if (code < 0)
148
	    return code;
149
    } else {			/* matrix operand */
150
	gs_matrix mat;
151
 
152
	/* The num_params failure might be a stack underflow. */
153
	check_op(2);
154
	if ((code = num_params(op - 1, 2, scale)) < 0 ||
155
	    (code = gs_make_scaling(scale[0], scale[1], &mat)) < 0 ||
156
	    (code = write_matrix(op, &mat)) < 0
157
	    ) {			/* Might be a stack underflow. */
158
	    check_op(3);
159
	    return code;
160
	}
161
	op[-2] = *op;
162
    }
163
    pop(2);
164
    return code;
165
}
166
 
167
/* <angle> rotate - */
168
/* <angle> <matrix> rotate <matrix> */
169
private int
170
zrotate(i_ctx_t *i_ctx_p)
171
{
172
    os_ptr op = osp;
173
    int code;
174
    double ang;
175
 
176
    if ((code = real_param(op, &ang)) >= 0) {
177
	code = gs_rotate(igs, ang);
178
	if (code < 0)
179
	    return code;
180
    } else {			/* matrix operand */
181
	gs_matrix mat;
182
 
183
	/* The num_params failure might be a stack underflow. */
184
	check_op(1);
185
	if ((code = num_params(op - 1, 1, &ang)) < 0 ||
186
	    (code = gs_make_rotation(ang, &mat)) < 0 ||
187
	    (code = write_matrix(op, &mat)) < 0
188
	    ) {			/* Might be a stack underflow. */
189
	    check_op(2);
190
	    return code;
191
	}
192
	op[-1] = *op;
193
    }
194
    pop(1);
195
    return code;
196
}
197
 
198
/* <matrix> concat - */
199
private int
200
zconcat(i_ctx_t *i_ctx_p)
201
{
202
    os_ptr op = osp;
203
    gs_matrix mat;
204
    int code = read_matrix(imemory, op, &mat);
205
 
206
    if (code < 0)
207
	return code;
208
    code = gs_concat(igs, &mat);
209
    if (code < 0)
210
	return code;
211
    pop(1);
212
    return 0;
213
}
214
 
215
/* <matrix1> <matrix2> <matrix> concatmatrix <matrix> */
216
private int
217
zconcatmatrix(i_ctx_t *i_ctx_p)
218
{
219
    os_ptr op = osp;
220
    gs_matrix m1, m2, mp;
221
    int code;
222
 
223
    if ((code = read_matrix(imemory, op - 2, &m1)) < 0 ||
224
	(code = read_matrix(imemory, op - 1, &m2)) < 0 ||
225
	(code = gs_matrix_multiply(&m1, &m2, &mp)) < 0 ||
226
	(code = write_matrix(op, &mp)) < 0
227
	)
228
	return code;
229
    op[-2] = *op;
230
    pop(2);
231
    return code;
232
}
233
 
234
/* <x> <y> transform <xt> <yt> */
235
/* <x> <y> <matrix> transform <xt> <yt> */
236
private int
237
ztransform(i_ctx_t *i_ctx_p)
238
{
239
    return common_transform(i_ctx_p, gs_transform, gs_point_transform);
240
}
241
 
242
/* <dx> <dy> dtransform <dxt> <dyt> */
243
/* <dx> <dy> <matrix> dtransform <dxt> <dyt> */
244
private int
245
zdtransform(i_ctx_t *i_ctx_p)
246
{
247
    return common_transform(i_ctx_p, gs_dtransform, gs_distance_transform);
248
}
249
 
250
/* <xt> <yt> itransform <x> <y> */
251
/* <xt> <yt> <matrix> itransform <x> <y> */
252
private int
253
zitransform(i_ctx_t *i_ctx_p)
254
{
255
    return common_transform(i_ctx_p, gs_itransform, gs_point_transform_inverse);
256
}
257
 
258
/* <dxt> <dyt> idtransform <dx> <dy> */
259
/* <dxt> <dyt> <matrix> idtransform <dx> <dy> */
260
private int
261
zidtransform(i_ctx_t *i_ctx_p)
262
{
263
    return common_transform(i_ctx_p, gs_idtransform, gs_distance_transform_inverse);
264
}
265
 
266
/* Common logic for [i][d]transform */
267
private int
268
common_transform(i_ctx_t *i_ctx_p,
269
	int (*ptproc)(gs_state *, floatp, floatp, gs_point *),
270
	int (*matproc)(floatp, floatp, const gs_matrix *, gs_point *))
271
{
272
    os_ptr op = osp;
273
    double opxy[2];
274
    gs_point pt;
275
    int code;
276
 
277
    /* Optimize for the non-matrix case */
278
    switch (r_type(op)) {
279
	case t_real:
280
	    opxy[1] = op->value.realval;
281
	    break;
282
	case t_integer:
283
	    opxy[1] = op->value.intval;
284
	    break;
285
	case t_array:		/* might be a matrix */
286
	case t_shortarray:
287
	case t_mixedarray: {
288
	    gs_matrix mat;
289
	    gs_matrix *pmat = &mat;
290
 
291
	    if ((code = read_matrix(imemory, op, pmat)) < 0 ||
292
		(code = num_params(op - 1, 2, opxy)) < 0 ||
293
		(code = (*matproc) (opxy[0], opxy[1], pmat, &pt)) < 0
294
		) {		/* Might be a stack underflow. */
295
		check_op(3);
296
		return code;
297
	    }
298
	    op--;
299
	    pop(1);
300
	    goto out;
301
	}
302
	default:
303
	    return_op_typecheck(op);
304
    }
305
    switch (r_type(op - 1)) {
306
	case t_real:
307
	    opxy[0] = (op - 1)->value.realval;
308
	    break;
309
	case t_integer:
310
	    opxy[0] = (op - 1)->value.intval;
311
	    break;
312
	default:
313
	    return_op_typecheck(op - 1);
314
    }
315
    if ((code = (*ptproc) (igs, opxy[0], opxy[1], &pt)) < 0)
316
	return code;
317
out:
318
    make_real(op - 1, pt.x);
319
    make_real(op, pt.y);
320
    return 0;
321
}
322
 
323
/* <matrix> <inv_matrix> invertmatrix <inv_matrix> */
324
private int
325
zinvertmatrix(i_ctx_t *i_ctx_p)
326
{
327
    os_ptr op = osp;
328
    gs_matrix m;
329
    int code;
330
 
331
    if ((code = read_matrix(imemory, op - 1, &m)) < 0 ||
332
	(code = gs_matrix_invert(&m, &m)) < 0 ||
333
	(code = write_matrix(op, &m)) < 0
334
	)
335
	return code;
336
    op[-1] = *op;
337
    pop(1);
338
    return code;
339
}
340
 
341
/* ------ Initialization procedure ------ */
342
 
343
const op_def zmatrix_op_defs[] =
344
{
345
    {"1concat", zconcat},
346
    {"2dtransform", zdtransform},
347
    {"3concatmatrix", zconcatmatrix},
348
    {"0.currentmatrix", zcurrentmatrix},
349
    {"1defaultmatrix", zdefaultmatrix},
350
    {"2idtransform", zidtransform},
351
    {"0initmatrix", zinitmatrix},
352
    {"2invertmatrix", zinvertmatrix},
353
    {"2itransform", zitransform},
354
    {"1rotate", zrotate},
355
    {"2scale", zscale},
356
    {"6.setmatrix", zsetmatrix},
357
    {"1.setdefaultmatrix", zsetdefaultmatrix},
358
    {"2transform", ztransform},
359
    {"2translate", ztranslate},
360
    op_def_end(0)
361
};