2 * Copyright © 2007 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 #include "rrtransform.h"
27 RRTransformInit(RRTransformPtr transform
)
29 pixman_transform_init_identity(&transform
->transform
);
30 pixman_f_transform_init_identity(&transform
->f_transform
);
31 pixman_f_transform_init_identity(&transform
->f_inverse
);
32 transform
->filter
= NULL
;
33 transform
->params
= NULL
;
34 transform
->nparams
= 0;
38 RRTransformFini(RRTransformPtr transform
)
40 free(transform
->params
);
44 RRTransformEqual(RRTransformPtr a
, RRTransformPtr b
)
46 if (a
&& pixman_transform_is_identity(&a
->transform
))
48 if (b
&& pixman_transform_is_identity(&b
->transform
))
50 if (a
== NULL
&& b
== NULL
)
52 if (a
== NULL
|| b
== NULL
)
54 if (memcmp(&a
->transform
, &b
->transform
, sizeof(a
->transform
)) != 0)
56 if (a
->filter
!= b
->filter
)
58 if (a
->nparams
!= b
->nparams
)
60 if (memcmp(a
->params
, b
->params
, a
->nparams
* sizeof(xFixed
)) != 0)
66 RRTransformSetFilter(RRTransformPtr dst
,
68 xFixed
* params
, int nparams
, int width
, int height
)
73 new_params
= malloc(nparams
* sizeof(xFixed
));
76 memcpy(new_params
, params
, nparams
* sizeof(xFixed
));
82 dst
->params
= new_params
;
83 dst
->nparams
= nparams
;
90 RRTransformCopy(RRTransformPtr dst
, RRTransformPtr src
)
92 if (src
&& pixman_transform_is_identity(&src
->transform
))
96 if (!RRTransformSetFilter(dst
, src
->filter
,
97 src
->params
, src
->nparams
, src
->width
,
100 dst
->transform
= src
->transform
;
101 dst
->f_transform
= src
->f_transform
;
102 dst
->f_inverse
= src
->f_inverse
;
105 if (!RRTransformSetFilter(dst
, NULL
, NULL
, 0, 0, 0))
107 pixman_transform_init_identity(&dst
->transform
);
108 pixman_f_transform_init_identity(&dst
->f_transform
);
109 pixman_f_transform_init_identity(&dst
->f_inverse
);
114 #define F(x) IntToxFixed(x)
117 RRTransformRescale(struct pixman_f_transform
*f_transform
, double limit
)
119 double max
= 0, v
, scale
;
122 for (j
= 0; j
< 3; j
++)
123 for (i
= 0; i
< 3; i
++)
124 if ((v
= abs(f_transform
->m
[j
][i
])) > max
)
127 for (j
= 0; j
< 3; j
++)
128 for (i
= 0; i
< 3; i
++)
129 f_transform
->m
[j
][i
] *= scale
;
133 * Compute the complete transformation matrix including
134 * client-specified transform, rotation/reflection values and the crtc
137 * Return TRUE if the resulting transform is not a simple translation.
140 RRTransformCompute(int x
,
145 RRTransformPtr rr_transform
,
146 PictTransformPtr transform
,
147 struct pixman_f_transform
*f_transform
,
148 struct pixman_f_transform
*f_inverse
)
150 PictTransform t_transform
, inverse
;
151 struct pixman_f_transform tf_transform
, tf_inverse
;
152 Bool overflow
= FALSE
;
155 transform
= &t_transform
;
157 f_transform
= &tf_transform
;
159 f_inverse
= &tf_inverse
;
161 pixman_transform_init_identity(transform
);
162 pixman_transform_init_identity(&inverse
);
163 pixman_f_transform_init_identity(f_transform
);
164 pixman_f_transform_init_identity(f_inverse
);
165 if (rotation
!= RR_Rotate_0
) {
166 double f_rot_cos
, f_rot_sin
, f_rot_dx
, f_rot_dy
;
167 double f_scale_x
, f_scale_y
, f_scale_dx
, f_scale_dy
;
168 xFixed rot_cos
, rot_sin
, rot_dx
, rot_dy
;
169 xFixed scale_x
, scale_y
, scale_dx
, scale_dy
;
172 switch (rotation
& 0xf) {
216 pixman_transform_rotate(transform
, &inverse
, rot_cos
, rot_sin
);
217 pixman_transform_translate(transform
, &inverse
, rot_dx
, rot_dy
);
218 pixman_f_transform_rotate(f_transform
, f_inverse
, f_rot_cos
, f_rot_sin
);
219 pixman_f_transform_translate(f_transform
, f_inverse
, f_rot_dx
,
231 if (rotation
& RR_Reflect_X
) {
234 if (rotation
& (RR_Rotate_0
| RR_Rotate_180
)) {
240 scale_dx
= F(height
);
243 if (rotation
& RR_Reflect_Y
) {
246 if (rotation
& (RR_Rotate_0
| RR_Rotate_180
)) {
248 scale_dy
= F(height
);
256 pixman_transform_scale(transform
, &inverse
, scale_x
, scale_y
);
257 pixman_f_transform_scale(f_transform
, f_inverse
, f_scale_x
, f_scale_y
);
258 pixman_transform_translate(transform
, &inverse
, scale_dx
, scale_dy
);
259 pixman_f_transform_translate(f_transform
, f_inverse
, f_scale_dx
,
263 #ifdef RANDR_12_INTERFACE
265 if (!pixman_transform_multiply
266 (transform
, &rr_transform
->transform
, transform
))
268 pixman_f_transform_multiply(f_transform
, &rr_transform
->f_transform
,
270 pixman_f_transform_multiply(f_inverse
, f_inverse
,
271 &rr_transform
->f_inverse
);
275 * Compute the class of the resulting transform
277 if (!overflow
&& pixman_transform_is_identity(transform
)) {
278 pixman_transform_init_translate(transform
, F(x
), F(y
));
280 pixman_f_transform_init_translate(f_transform
, x
, y
);
281 pixman_f_transform_init_translate(f_inverse
, -x
, -y
);
285 pixman_f_transform_translate(f_transform
, f_inverse
, x
, y
);
286 if (!pixman_transform_translate(transform
, &inverse
, F(x
), F(y
)))
289 struct pixman_f_transform f_scaled
;
291 f_scaled
= *f_transform
;
292 RRTransformRescale(&f_scaled
, 16384.0);
293 pixman_transform_from_pixman_f_transform(transform
, &f_scaled
);