1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
17 #include "transform.h"
25 GeneralTransform::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
27 if (args
->GetProperty ()->GetOwnerType() == Type::DEPENDENCY_OBJECT
) {
28 DependencyObject::OnPropertyChanged (args
, error
);
34 // If the transform changes, we need to notify our owners
35 // that they must repaint (all of our properties have
38 // There is no need to override this on the base classes
39 // as they are sealed, so no new properties can be added
40 // and I do not believe that we can create new instances
41 // of transform from C#, and in that case, we would only
44 NotifyListenersOfPropertyChange (args
, error
);
48 GeneralTransform::UpdateTransform ()
50 g_warning ("GeneralTransform::UpdateTransform has been called. The derived class should have overridden it.");
54 GeneralTransform::MaybeUpdateTransform ()
63 GeneralTransform::GetTransform (cairo_matrix_t
*value
)
65 MaybeUpdateTransform ();
70 GeneralTransform::GetMatrix ()
72 MaybeUpdateTransform ();
73 return new Matrix (&_matrix
);
77 GeneralTransform::Transform (Point point
)
79 MaybeUpdateTransform ();
80 return point
.Transform (&_matrix
);
84 general_transform_transform_point (GeneralTransform
*t
, Point
*p
, Point
*r
)
86 *r
= t
->Transform (*p
);
95 RotateTransform::UpdateTransform ()
97 double angle
, center_x
, center_y
;
101 center_x
= GetCenterX ();
102 center_y
= GetCenterY ();
104 radians
= angle
/ 180.0 * M_PI
;
106 if (center_x
== 0.0 && center_y
== 0.0) {
107 cairo_matrix_init_rotate (&_matrix
, radians
);
110 cairo_matrix_init_translate (&_matrix
, center_x
, center_y
);
111 cairo_matrix_rotate (&_matrix
, radians
);
112 cairo_matrix_translate (&_matrix
, -center_x
, -center_y
);
114 //printf ("Returning2 %g %g %g %g %g %g\n", value->xx, value->yx, value->xy, value->yy, value->x0, value->y0);
119 // TranslateTransform
123 TranslateTransform::UpdateTransform ()
128 cairo_matrix_init_translate (&_matrix
, x
, y
);
129 //printf ("translating dx %g dy %g", x, y);
130 //printf ("TranslateTransform %g %g %g %g %g %g\n", value->xx, value->yx, value->xy, value->yy, value->x0, value->y0);
137 ScaleTransform::UpdateTransform ()
139 double sx
= GetScaleX ();
140 double sy
= GetScaleY ();
142 // XXX you don't want to know. don't make these 0.00001, or
143 // else cairo spits out errors about non-invertable matrices
144 // (or worse, crashes)
146 // the 0.0 scales are caused in at least one instance by us
147 // being too aggressive at starting animations at time=0 when
148 // they're supposed to (unset, or 0:0:0 BeginTime)
150 if (sx
== 0.0) sx
= 0.00002;
151 if (sy
== 0.0) sy
= 0.00002;
153 double cx
= GetCenterX ();
154 double cy
= GetCenterY ();
156 if (cx
== 0.0 && cy
== 0.0) {
157 cairo_matrix_init_scale (&_matrix
, sx
, sy
);
160 cairo_matrix_init_translate (&_matrix
, cx
, cy
);
161 cairo_matrix_scale (&_matrix
, sx
, sy
);
162 cairo_matrix_translate (&_matrix
, -cx
, -cy
);
164 //printf ("scaling sx %g sy %g at center cx %g cy %g\n", sx, sy, cx, cy);
165 //printf ("ScaleTransform %g %g %g %g %g %g\n", value->xx, value->yx, value->xy, value->yy, value->x0, value->y0);
173 SkewTransform::UpdateTransform ()
175 double cx
= GetCenterX ();
176 double cy
= GetCenterY ();
178 bool translation
= ((cx
!= 0.0) || (cy
!= 0.0));
180 cairo_matrix_init_translate (&_matrix
, cx
, cy
);
182 cairo_matrix_init_identity (&_matrix
);
184 double ax
= GetAngleX ();
186 _matrix
.xy
= tan (ax
* M_PI
/ 180);
188 double ay
= GetAngleY ();
190 _matrix
.yx
= tan (ay
* M_PI
/ 180);
193 cairo_matrix_translate (&_matrix
, -cx
, -cy
);
195 //printf ("SkewTransform %g %g %g %g %g %g\n", value->xx, value->yx, value->xy, value->yy, value->x0, value->y0);
204 SetObjectType (Type::MATRIX
);
205 cairo_matrix_init_identity (&matrix
);
208 Matrix::Matrix(cairo_matrix_t
*m
)
210 SetObjectType (Type::MATRIX
);
216 SetOffsetX (matrix
.x0
);
217 SetOffsetY (matrix
.y0
);
221 Matrix::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
223 if (args
->GetProperty ()->GetOwnerType() != Type::MATRIX
) {
224 DependencyObject::OnPropertyChanged (args
, error
);
228 if (args
->GetId () == Matrix::M11Property
)
229 matrix
.xx
= args
->GetNewValue()->AsDouble ();
230 else if (args
->GetId () == Matrix::M12Property
)
231 matrix
.yx
= args
->GetNewValue()->AsDouble ();
232 else if (args
->GetId () == Matrix::M21Property
)
233 matrix
.xy
= args
->GetNewValue()->AsDouble ();
234 else if (args
->GetId () == Matrix::M22Property
)
235 matrix
.yy
= args
->GetNewValue()->AsDouble ();
236 else if (args
->GetId () == Matrix::OffsetXProperty
)
237 matrix
.x0
= args
->GetNewValue()->AsDouble ();
238 else if (args
->GetId () == Matrix::OffsetYProperty
)
239 matrix
.y0
= args
->GetNewValue()->AsDouble ();
241 NotifyListenersOfPropertyChange (args
, error
);
245 Matrix::GetUnderlyingMatrix ()
255 MatrixTransform::OnSubPropertyChanged (DependencyProperty
*prop
, DependencyObject
*obj
, PropertyChangedEventArgs
*subobj_args
)
259 DependencyObject::OnSubPropertyChanged (prop
, obj
, subobj_args
);
261 NotifyListenersOfPropertyChange (MatrixTransform::MatrixProperty
, NULL
);
265 MatrixTransform::UpdateTransform ()
267 Matrix
*matrix
= GetMatrix ();
269 _matrix
= matrix
->GetUnderlyingMatrix();
271 cairo_matrix_init_identity (&_matrix
);
278 TransformGroup::TransformGroup ()
280 SetObjectType (Type::TRANSFORMGROUP
);
284 TransformGroup::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
286 if (args
->GetProperty ()->GetOwnerType() != Type::TRANSFORMGROUP
) {
287 Transform::OnPropertyChanged (args
, error
);
291 if (args
->GetId () == TransformGroup::ChildrenProperty
) {
295 NotifyListenersOfPropertyChange (args
, error
);
299 TransformGroup::OnCollectionChanged (Collection
*col
, CollectionChangedEventArgs
*args
)
301 if (col
!= GetChildren ()) {
302 Transform::OnCollectionChanged (col
, args
);
307 NotifyListenersOfPropertyChange (TransformGroup::ChildrenProperty
, NULL
);
311 TransformGroup::OnCollectionItemChanged (Collection
*col
, DependencyObject
*obj
, PropertyChangedEventArgs
*args
)
313 if (col
!= GetChildren ()) {
314 Transform::OnCollectionItemChanged (col
, obj
, args
);
318 // Unit tests shows that the "cache" matrix value (exposed in SL2) is not updated when child items are changed.
319 // However SL2 does re-compute this value (if dirty) before drawing anything that depends on it.
320 // Currently Moonlight behave differently by always returning the "up to date" matrix
322 NotifyListenersOfPropertyChange (TransformGroup::ChildrenProperty
, NULL
);
326 TransformGroup::UpdateTransform ()
328 TransformCollection
*children
= GetChildren ();
330 cairo_matrix_init_identity (&_matrix
);
332 for (int i
= 0; i
< children
->GetCount (); i
++) {
333 Transform
*transform
= children
->GetValueAt (i
)->AsTransform ();
334 cairo_matrix_t matrix
;
336 transform
->GetTransform (&matrix
);
337 cairo_matrix_multiply (&_matrix
, &_matrix
, &matrix
);