1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * value.cpp: Implementation of for Value.
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.
27 #include "animation.h"
31 #include "cornerradius.h"
32 #include "mono/metadata/object.h"
33 #include "fontsource.h"
34 #include "transform.h"
39 * Value implementation
42 static const int NullFlag
= 1;
45 Value::CreateUnrefPtr (EventObject
* dob
)
47 Value
*result
= new Value (dob
);
48 LOG_VALUE ("unref Value [%p] %s\n", result
, result
->GetName());
55 Value::CreateUnref (EventObject
* dob
)
58 LOG_VALUE ("unref Value [%p] %s\n", &result
, result
.GetName());
64 Value::Clone (Value
*v
, Types
*types
)
70 types
= Deployment::GetCurrent()->GetTypes();
72 if (types
->IsSubclassOf (v
->k
, Type::DEPENDENCY_OBJECT
)) {
73 return new Value (v
->AsDependencyObject()->Clone (types
));
76 return new Value (*v
);
89 return (padding
& NullFlag
) == NullFlag
;
93 Value::SetIsNull (bool isNull
)
105 memset (&u
, 0, sizeof (u
));
115 Value::Value (const Value
& v
)
120 Value::Value (Type::Kind k
)
134 Value::Value (double d
)
142 Value::Value (gint64 i
, Type::Kind as
)
150 Value::Value (gint32 i
)
159 Value::Value (guint32 i
)
167 Value::Value (gunichar c
, Type::Kind as
)
175 Value::Value (Color c
)
179 u
.color
= g_new (Color
, 1);
180 *u
.color
= Color (c
);
184 Value::Value (EventObject
* obj
)
188 k
= Type::EVENTOBJECT
;
191 if (!Type::IsSubclassOf (obj
->GetObjectType (), Type::EVENTOBJECT
)) {
192 g_warning ("creating invalid dependency object Value");
194 u
.dependency_object
= NULL
;
197 k
= obj
->GetObjectType ();
198 LOG_VALUE (" ref Value [%p] %s\n", this, GetName());
202 u
.dependency_object
= obj
;
205 Value::Value (FontFamily family
)
208 k
= Type::FONTFAMILY
;
209 u
.fontfamily
= g_new (FontFamily
, 1);
210 u
.fontfamily
->source
= g_strdup (family
.source
);
214 Value::Value (FontWeight weight
)
217 k
= Type::FONTWEIGHT
;
218 u
.fontweight
= g_new (FontWeight
, 1);
219 u
.fontweight
->weight
= weight
.weight
;
223 Value::Value (FontStretch stretch
)
226 k
= Type::FONTSTRETCH
;
227 u
.fontstretch
= g_new (FontStretch
, 1);
228 u
.fontstretch
->stretch
= stretch
.stretch
;
232 Value::Value (FontStyle style
)
236 u
.fontstyle
= g_new (FontStyle
, 1);
237 u
.fontstyle
->style
= style
.style
;
241 Value::Value (FontSource source
)
244 k
= Type::FONTSOURCE
;
245 u
.fontsource
= g_new (FontSource
, 1);
246 u
.fontsource
->stream
= g_new (ManagedStreamCallbacks
, 1);
247 memcpy (u
.fontsource
->stream
, source
.stream
, sizeof (ManagedStreamCallbacks
));
251 Value::Value (PropertyPath propertypath
)
254 k
= Type::PROPERTYPATH
;
255 u
.propertypath
= g_new (PropertyPath
, 1);
256 u
.propertypath
->path
= g_strdup (propertypath
.path
);
257 u
.propertypath
->expanded_path
= g_strdup (propertypath
.expanded_path
);
258 u
.propertypath
->property
= propertypath
.property
;
262 Value::Value (Type::Kind kind
, void *npobj
)
266 u
.managed_object
= npobj
;
267 SetIsNull (npobj
== NULL
);
270 Value::Value (Point pt
)
274 u
.point
= g_new (Point
, 1);
275 *u
.point
= Point (pt
);
279 Value::Value (Uri uri
)
283 u
.uri
= g_new (Uri
, 1);
284 Uri::Copy (&uri
, u
.uri
);
288 Value::Value (Rect rect
)
292 u
.rect
= g_new (Rect
, 1);
293 *u
.rect
= Rect (rect
);
297 Value::Value (Size size
)
301 u
.size
= g_new (Size
, 1);
302 *u
.size
= Size (size
);
306 Value::Value (RepeatBehavior repeat
)
309 k
= Type::REPEATBEHAVIOR
;
310 u
.repeat
= g_new (RepeatBehavior
, 1);
311 *u
.repeat
= RepeatBehavior (repeat
);
315 Value::Value (Duration duration
)
319 u
.duration
= g_new (Duration
, 1);
320 *u
.duration
= Duration (duration
);
324 Value::Value (KeyTime keytime
)
328 u
.keytime
= g_new (KeyTime
, 1);
329 *u
.keytime
= KeyTime (keytime
);
333 Value::Value (const char *s
, bool take
)
338 u
.s
= take
? (char *) s
: g_strdup (s
);
339 SetIsNull (s
== NULL
);
342 Value::Value (GridLength grid_length
)
345 k
= Type::GRIDLENGTH
;
346 u
.grid_length
= g_new (GridLength
, 1);
347 *u
.grid_length
= GridLength (grid_length
);
351 Value::Value (Thickness thickness
)
355 u
.thickness
= g_new (Thickness
, 1);
356 *u
.thickness
= Thickness (thickness
);
360 Value::Value (CornerRadius corner
)
363 k
= Type::CORNERRADIUS
;
364 u
.corner
= g_new (CornerRadius
, 1);
365 *u
.corner
= CornerRadius (corner
);
369 Value::Value (ManagedTypeInfo type_info
)
372 k
= Type::MANAGEDTYPEINFO
;
373 u
.type_info
= g_new (ManagedTypeInfo
, 1);
374 *u
.type_info
= ManagedTypeInfo (type_info
);
379 Value::Copy (const Value
& v
)
385 SetIsNull (((Value
&)v
).GetIsNull());
387 /* make a copy of the string instead of just the pointer */
390 u
.s
= g_strdup (v
.u
.s
);
392 case Type::FONTFAMILY
:
393 if (v
.u
.fontfamily
) {
394 u
.fontfamily
= g_new (FontFamily
, 1);
395 u
.fontfamily
->source
= g_strdup (v
.u
.fontfamily
->source
);
398 case Type::FONTSOURCE
:
399 if (v
.u
.fontsource
) {
400 u
.fontsource
= g_new (FontSource
, 1);
401 u
.fontsource
->stream
= g_new (ManagedStreamCallbacks
, 1);
402 memcpy (u
.fontsource
->stream
, v
.u
.fontsource
->stream
, sizeof (ManagedStreamCallbacks
));
405 case Type::FONTWEIGHT
:
406 if (v
.u
.fontweight
) {
407 u
.fontweight
= g_new (FontWeight
, 1);
408 *u
.fontweight
= *v
.u
.fontweight
;
411 case Type::FONTSTRETCH
:
412 if (v
.u
.fontstretch
) {
413 u
.fontstretch
= g_new (FontStretch
, 1);
414 *u
.fontstretch
= *v
.u
.fontstretch
;
417 case Type::FONTSTYLE
:
419 u
.fontstyle
= g_new (FontStyle
, 1);
420 *u
.fontstyle
= *v
.u
.fontstyle
;
423 case Type::PROPERTYPATH
:
424 if (v
.u
.propertypath
) {
425 u
.propertypath
= g_new (PropertyPath
, 1);
426 u
.propertypath
->path
= g_strdup (v
.u
.propertypath
->path
);
427 u
.propertypath
->expanded_path
= g_strdup (v
.u
.propertypath
->expanded_path
);
428 u
.propertypath
->property
= v
.u
.propertypath
->property
;
433 u
.color
= g_new (Color
, 1);
434 *u
.color
= *v
.u
.color
;
439 u
.point
= g_new (Point
, 1);
440 *u
.point
= *v
.u
.point
;
445 u
.rect
= g_new (Rect
, 1);
451 u
.size
= g_new (Size
, 1);
457 u
.uri
= g_new (Uri
, 1);
458 Uri::Copy (v
.u
.uri
, u
.uri
);
463 case Type::REPEATBEHAVIOR
:
465 u
.repeat
= g_new (RepeatBehavior
, 1);
466 *u
.repeat
= *v
.u
.repeat
;
471 u
.duration
= g_new (Duration
, 1);
472 *u
.duration
= *v
.u
.duration
;
477 u
.keytime
= g_new (KeyTime
, 1);
478 *u
.keytime
= *v
.u
.keytime
;
481 case Type::GRIDLENGTH
:
482 if (v
.u
.grid_length
) {
483 u
.grid_length
= g_new (GridLength
, 1);
484 *u
.grid_length
= *v
.u
.grid_length
;
487 case Type::THICKNESS
:
489 u
.thickness
= g_new (Thickness
, 1);
490 *u
.thickness
= *v
.u
.thickness
;
493 case Type::CORNERRADIUS
:
495 u
.corner
= g_new (CornerRadius
, 1);
496 *u
.corner
= *v
.u
.corner
;
499 case Type::MANAGEDTYPEINFO
:
501 u
.type_info
= g_new (ManagedTypeInfo
, 1);
502 *u
.type_info
= *v
.u
.type_info
;
506 if (Is (Type::EVENTOBJECT
) && u
.dependency_object
) {
507 LOG_VALUE (" ref Value [%p] %s\n", this, GetName());
508 u
.dependency_object
->ref ();
517 switch (GetKind ()) {
524 case Type::FONTFAMILY
:
526 g_free (u
.fontfamily
->source
);
527 g_free (u
.fontfamily
);
530 case Type::FONTWEIGHT
:
531 g_free (u
.fontweight
);
533 case Type::FONTSTYLE
:
534 g_free (u
.fontstyle
);
536 case Type::FONTSTRETCH
:
537 g_free (u
.fontstretch
);
539 case Type::FONTSOURCE
:
541 g_free (u
.fontsource
->stream
);
542 g_free (u
.fontsource
);
545 case Type::PROPERTYPATH
:
546 if (u
.propertypath
) {
547 g_free (u
.propertypath
->path
);
548 g_free (u
.propertypath
->expanded_path
);
549 g_free (u
.propertypath
);
567 case Type::REPEATBEHAVIOR
:
576 case Type::GRIDLENGTH
:
577 g_free (u
.grid_length
);
579 case Type::THICKNESS
:
580 g_free (u
.thickness
);
582 case Type::CORNERRADIUS
:
586 if (Is (Type::EVENTOBJECT
) && u
.dependency_object
) {
587 LOG_VALUE ("unref Value [%p] %s\n", this, GetName());
588 u
.dependency_object
->unref ();
596 GString
*str
= g_string_new ("");
600 g_string_append_printf (str
, "{ %f }", u
.d
);
603 g_string_append (str
, u
.s
);
606 g_string_append_printf (str
, "{%g/%g/%g/%g}", u
.color
->r
, u
.color
->g
, u
.color
->b
, u
.color
->a
);
609 g_string_append_printf (str
, "{ %g, %g }", (u
.point
)->x
, (u
.point
)->y
);
612 g_string_append_printf (str
, "{ %g, %g }", (u
.size
)->width
, (u
.size
)->height
);
615 g_string_append_printf (str
, "{ x=%g, y=%g, w=%g, h=%g }", (u
.rect
)->x
, (u
.rect
)->y
, (u
.rect
)->width
, (u
.rect
)->height
);
617 case Type::REPEATBEHAVIOR
:
618 if (u
.repeat
->IsForever ())
619 g_string_append (str
, "{repeat=forever}");
620 else if ((u
.repeat
)->HasDuration ())
621 g_string_append_printf (str
, "{repeat=duration}");
622 else if ((u
.repeat
)->HasCount ())
623 g_string_append_printf (str
, "{repeat=count %g}", (u
.repeat
)->GetCount ());
625 case Type::THICKNESS
:
626 g_string_append_printf (str
, "{ l=%g, t=%g, r=%g, b=%g }", (u
.thickness
)->left
, (u
.thickness
)->top
, (u
.thickness
)->right
, (u
.thickness
)->bottom
);
629 g_string_append_printf (str
, "{duration/TODO}");
632 g_string_append_printf (str
, "{keytime/TODO}");
634 case Type::GRIDLENGTH
:
635 g_string_append_printf (str
, "{gridlength value:%.2f type:%d}", u
.grid_length
->val
, u
.grid_length
->type
);
638 if (Is (Type::EVENTOBJECT
) && u
.dependency_object
)
639 g_string_append_printf (str
, "[%s <%s>]", u
.dependency_object
->GetTypeName (), Is (Type::DEPENDENCY_OBJECT
) ? AsDependencyObject ()->GetName () : "no name");
641 g_string_append_printf (str
, "UnknownType");
645 return g_string_free (str
, FALSE
);
649 Value::operator!= (const Value
&v
) const
651 return !(*this == v
);
655 Value::operator== (const Value
&v
) const
660 if (padding
!= v
.padding
)
666 return v
.u
.s
== NULL
;
667 } else if (v
.u
.s
== NULL
)
670 return !strcmp (u
.s
, v
.u
.s
);
671 case Type::FONTFAMILY
:
672 return *u
.fontfamily
== *v
.u
.fontfamily
;
673 case Type::FONTWEIGHT
:
674 return *u
.fontweight
== *v
.u
.fontweight
;
675 case Type::FONTSTYLE
:
676 return *u
.fontstyle
== *v
.u
.fontstyle
;
677 case Type::FONTSTRETCH
:
678 return *u
.fontstretch
== *v
.u
.fontstretch
;
679 case Type::FONTSOURCE
:
680 if (u
.fontsource
&& v
.u
.fontsource
)
681 return u
.fontsource
->stream
->handle
== v
.u
.fontsource
->stream
->handle
;
682 return u
.fontsource
== v
.u
.fontsource
;
683 case Type::PROPERTYPATH
:
684 return *u
.propertypath
== *v
.u
.propertypath
;
686 return !memcmp (u
.color
, v
.u
.color
, sizeof (Color
));
688 return !memcmp (u
.point
, v
.u
.point
, sizeof (Point
));
690 return !memcmp (u
.rect
, v
.u
.rect
, sizeof (Rect
));
692 return !memcmp (u
.size
, v
.u
.size
, sizeof (Size
));
693 case Type::REPEATBEHAVIOR
:
694 // memcmp can't be used since the struct contains unassigned padding value
695 return *u
.repeat
== *v
.u
.repeat
;
697 // memcmp can't be used since the struct contains unassigned padding value
698 return *u
.duration
== *v
.u
.duration
;
700 // memcmp can't be used since the struct contains unassigned padding value
701 return *u
.keytime
== *v
.u
.keytime
;
702 case Type::GRIDLENGTH
:
703 return !memcmp (u
.grid_length
, v
.u
.grid_length
, sizeof (GridLength
));
704 case Type::THICKNESS
:
705 return !memcmp (u
.thickness
, v
.u
.thickness
, sizeof (Thickness
));
706 case Type::CORNERRADIUS
:
707 return !memcmp (u
.corner
, v
.u
.corner
, sizeof (CornerRadius
));
708 case Type::MANAGEDTYPEINFO
:
709 return !memcmp (u
.type_info
, v
.u
.type_info
, sizeof (ManagedTypeInfo
));
715 return *u
.uri
== *v
.u
.uri
;
716 case Type::MANAGED
: {
717 // If we avoid the cast to 64bit uint, i don't know how to implement this sanity check.
718 //g_return_val_if_fail (a == (a & 0xFFFFFFFF) && b == (b & 0xFFFFFFFF), false);
719 guint32 a
= GPOINTER_TO_INT (u
.managed_object
);
720 guint32 b
= GPOINTER_TO_INT (v
.u
.managed_object
);
721 return mono_gchandle_get_target (a
) == mono_gchandle_get_target (b
);
725 return !memcmp (&u
, &v
.u
, sizeof (u
));
732 Value::operator= (const Value
& other
)
740 // This is invoked by managed code to free the contents of the value
743 value_free_value (Value
* value
)
749 value_free_value2 (Value
*value
)
751 value_free_value (value
);
763 GString
*str
= g_string_new ("");
767 g_string_append_printf (str
, "DOUBLE");
770 g_string_append_printf (str
, "STRING");
773 g_string_append_printf (str
, "COLOR");
776 g_string_append_printf (str
, "POINT");
779 g_string_append_printf (str
, "SIZE");
782 g_string_append_printf (str
, "RECT");
784 case Type::REPEATBEHAVIOR
:
785 g_string_append_printf (str
, "REPEATBEHAVIOR");
787 case Type::THICKNESS
:
788 g_string_append_printf (str
, "THICKNESS");
791 g_string_append_printf (str
, "DURATION");
794 g_string_append_printf (str
, "KEYTIME");
796 case Type::GRIDLENGTH
:
797 g_string_append_printf (str
, "GRIDLENGTH");
800 if (u
.dependency_object
)
801 g_string_append_printf (str
, "[%s] [%p] %d", u
.dependency_object
->GetTypeName (), u
.dependency_object
, u
.dependency_object
->GetRefCount ());
803 g_string_append_printf (str
, "UnknownType");
807 return g_string_free (str
, FALSE
);