1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: zmatrix.c 9300 2008-12-21 07:46:52Z alexcher $ */
15
/* Matrix operators */
23
/* Forward references */
24
static int common_transform(i_ctx_t *,
25
int (*)(gs_state *, floatp, floatp, gs_point *),
26
int (*)(floatp, floatp, const gs_matrix *, gs_point *));
30
zinitmatrix(i_ctx_t *i_ctx_p)
32
return gs_initmatrix(igs);
35
/* <matrix> defaultmatrix <matrix> */
37
zdefaultmatrix(i_ctx_t *i_ctx_p)
42
gs_defaultmatrix(igs, &mat);
43
return write_matrix(op, &mat);
46
/* - .currentmatrix <xx> <xy> <yx> <yy> <tx> <ty> */
48
zcurrentmatrix(i_ctx_t *i_ctx_p)
52
int code = gs_currentmatrix(igs, &mat);
57
code = make_floats(op - 5, &mat.xx, 6);
63
/* <xx> <xy> <yx> <yy> <tx> <ty> .setmatrix - */
65
zsetmatrix(i_ctx_t *i_ctx_p)
69
int code = float_params(op, 6, &mat.xx);
73
if ((code = gs_setmatrix(igs, &mat)) < 0)
79
/* <matrix|null> .setdefaultmatrix - */
81
zsetdefaultmatrix(i_ctx_t *i_ctx_p)
86
if (r_has_type(op, t_null))
87
code = gs_setdefaultmatrix(igs, NULL);
91
code = read_matrix(imemory, op, &mat);
94
code = gs_setdefaultmatrix(igs, &mat);
102
/* <tx> <ty> translate - */
103
/* <tx> <ty> <matrix> translate <matrix> */
105
ztranslate(i_ctx_t *i_ctx_p)
111
if ((code = num_params(op, 2, trans)) >= 0) {
112
code = gs_translate(igs, trans[0], trans[1]);
115
} else { /* matrix operand */
118
/* The num_params failure might be a stack underflow. */
120
if ((code = num_params(op - 1, 2, trans)) < 0 ||
121
(code = gs_make_translation(trans[0], trans[1], &mat)) < 0 ||
122
(code = write_matrix(op, &mat)) < 0
123
) { /* Might be a stack underflow. */
133
/* <sx> <sy> scale - */
134
/* <sx> <sy> <matrix> scale <matrix> */
136
zscale(i_ctx_t *i_ctx_p)
142
if ((code = num_params(op, 2, scale)) >= 0) {
143
code = gs_scale(igs, scale[0], scale[1]);
146
} else { /* matrix operand */
149
/* The num_params failure might be a stack underflow. */
151
if ((code = num_params(op - 1, 2, scale)) < 0 ||
152
(code = gs_make_scaling(scale[0], scale[1], &mat)) < 0 ||
153
(code = write_matrix(op, &mat)) < 0
154
) { /* Might be a stack underflow. */
164
/* <angle> rotate - */
165
/* <angle> <matrix> rotate <matrix> */
167
zrotate(i_ctx_t *i_ctx_p)
173
if ((code = real_param(op, &ang)) >= 0) {
174
code = gs_rotate(igs, ang);
177
} else { /* matrix operand */
180
/* The num_params failure might be a stack underflow. */
182
if ((code = num_params(op - 1, 1, &ang)) < 0 ||
183
(code = gs_make_rotation(ang, &mat)) < 0 ||
184
(code = write_matrix(op, &mat)) < 0
185
) { /* Might be a stack underflow. */
195
/* <matrix> concat - */
197
zconcat(i_ctx_t *i_ctx_p)
201
int code = read_matrix(imemory, op, &mat);
205
code = gs_concat(igs, &mat);
212
/* <matrix1> <matrix2> <matrix> concatmatrix <matrix> */
214
zconcatmatrix(i_ctx_t *i_ctx_p)
217
gs_matrix m1, m2, mp;
220
if ((code = read_matrix(imemory, op - 2, &m1)) < 0 ||
221
(code = read_matrix(imemory, op - 1, &m2)) < 0 ||
222
(code = gs_matrix_multiply(&m1, &m2, &mp)) < 0 ||
223
(code = write_matrix(op, &mp)) < 0
231
/* <x> <y> transform <xt> <yt> */
232
/* <x> <y> <matrix> transform <xt> <yt> */
234
ztransform(i_ctx_t *i_ctx_p)
236
return common_transform(i_ctx_p, gs_transform, gs_point_transform);
239
/* <dx> <dy> dtransform <dxt> <dyt> */
240
/* <dx> <dy> <matrix> dtransform <dxt> <dyt> */
242
zdtransform(i_ctx_t *i_ctx_p)
244
return common_transform(i_ctx_p, gs_dtransform, gs_distance_transform);
247
/* <xt> <yt> itransform <x> <y> */
248
/* <xt> <yt> <matrix> itransform <x> <y> */
250
zitransform(i_ctx_t *i_ctx_p)
252
return common_transform(i_ctx_p, gs_itransform, gs_point_transform_inverse);
255
/* <dxt> <dyt> idtransform <dx> <dy> */
256
/* <dxt> <dyt> <matrix> idtransform <dx> <dy> */
258
zidtransform(i_ctx_t *i_ctx_p)
260
return common_transform(i_ctx_p, gs_idtransform, gs_distance_transform_inverse);
263
/* Common logic for [i][d]transform */
265
common_transform(i_ctx_t *i_ctx_p,
266
int (*ptproc)(gs_state *, floatp, floatp, gs_point *),
267
int (*matproc)(floatp, floatp, const gs_matrix *, gs_point *))
274
/* Optimize for the non-matrix case */
275
switch (r_type(op)) {
277
opxy[1] = op->value.realval;
280
opxy[1] = op->value.intval;
282
case t_array: /* might be a matrix */
286
gs_matrix *pmat = &mat;
288
if ((code = read_matrix(imemory, op, pmat)) < 0 ||
289
(code = num_params(op - 1, 2, opxy)) < 0 ||
290
(code = (*matproc) (opxy[0], opxy[1], pmat, &pt)) < 0
291
) { /* Might be a stack underflow. */
300
return_op_typecheck(op);
302
switch (r_type(op - 1)) {
304
opxy[0] = (op - 1)->value.realval;
307
opxy[0] = (op - 1)->value.intval;
310
return_op_typecheck(op - 1);
312
if ((code = (*ptproc) (igs, opxy[0], opxy[1], &pt)) < 0)
315
make_real(op - 1, pt.x);
320
/* <matrix> <inv_matrix> invertmatrix <inv_matrix> */
322
zinvertmatrix(i_ctx_t *i_ctx_p)
328
if ((code = read_matrix(imemory, op - 1, &m)) < 0 ||
329
(code = gs_matrix_invert(&m, &m)) < 0 ||
330
(code = write_matrix(op, &m)) < 0
338
/* <bbox> <matrix> .bbox_transform <x0> <y0> <x1> <y1> */
339
/* Calculate bonding box of a box transformed by a matrix. */
341
zbbox_transform(i_ctx_t *i_ctx_p)
346
gs_point aa, az, za, zz;
350
if ((code = read_matrix(imemory, op, &m)) < 0)
353
if (!r_is_array(op - 1))
354
return_op_typecheck(op - 1);
356
if (r_size(op - 1) != 4)
357
return_error(e_rangecheck);
358
if ((code = process_float_array(imemory, op - 1, 4, bbox) < 0))
361
gs_point_transform(bbox[0], bbox[1], &m, &aa);
362
gs_point_transform(bbox[0], bbox[3], &m, &az);
363
gs_point_transform(bbox[2], bbox[1], &m, &za);
364
gs_point_transform(bbox[2], bbox[3], &m, &zz);
367
temp = aa.x, aa.x = az.x, az.x = temp;
369
temp = za.x, za.x = zz.x, zz.x = temp;
371
aa.x = za.x; /* min */
373
zz.x = az.x; /* max */
376
temp = aa.y, aa.y = az.y, az.y = temp;
378
temp = za.y, za.y = zz.y, zz.y = temp;
380
aa.y = za.y; /* min */
382
zz.y = az.y; /* max */
385
make_real(op - 3, (float)aa.x);
386
make_real(op - 2, (float)aa.y);
387
make_real(op - 1, (float)zz.x);
388
make_real(op , (float)zz.y);
392
/* ------ Initialization procedure ------ */
394
const op_def zmatrix_op_defs[] =
396
{"1concat", zconcat},
397
{"2dtransform", zdtransform},
398
{"3concatmatrix", zconcatmatrix},
399
{"0.currentmatrix", zcurrentmatrix},
400
{"1defaultmatrix", zdefaultmatrix},
401
{"2idtransform", zidtransform},
402
{"0initmatrix", zinitmatrix},
403
{"2invertmatrix", zinvertmatrix},
404
{"2itransform", zitransform},
405
{"1rotate", zrotate},
407
{"6.setmatrix", zsetmatrix},
408
{"1.setdefaultmatrix", zsetdefaultmatrix},
409
{"2transform", ztransform},
410
{"2translate", ztranslate},
414
const op_def zmatrix2_op_defs[] =
416
{"2.bbox_transform", zbbox_transform},