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
)
102 Value::Set (double value
)
111 memset (&u
, 0, sizeof (u
));
121 Value::Value (const Value
& v
)
126 Value::Value (Type::Kind k
)
140 Value::Value (double d
)
148 Value::Value (gint64 i
, Type::Kind as
)
156 Value::Value (gint32 i
)
165 Value::Value (guint32 i
)
173 Value::Value (gunichar c
, Type::Kind as
)
181 Value::Value (Color c
)
185 u
.color
= g_new (Color
, 1);
186 *u
.color
= Color (c
);
190 Value::Value (EventObject
* obj
)
194 k
= Type::EVENTOBJECT
;
197 if (!Type::IsSubclassOf (obj
->GetObjectType (), Type::EVENTOBJECT
)) {
198 g_warning ("creating invalid dependency object Value");
200 u
.dependency_object
= NULL
;
203 k
= obj
->GetObjectType ();
204 LOG_VALUE (" ref Value [%p] %s\n", this, GetName());
208 u
.dependency_object
= obj
;
211 Value::Value (FontFamily family
)
214 k
= Type::FONTFAMILY
;
215 u
.fontfamily
= g_new (FontFamily
, 1);
216 u
.fontfamily
->source
= g_strdup (family
.source
);
220 Value::Value (FontWeight weight
)
223 k
= Type::FONTWEIGHT
;
224 u
.fontweight
= g_new (FontWeight
, 1);
225 u
.fontweight
->weight
= weight
.weight
;
229 Value::Value (FontStretch stretch
)
232 k
= Type::FONTSTRETCH
;
233 u
.fontstretch
= g_new (FontStretch
, 1);
234 u
.fontstretch
->stretch
= stretch
.stretch
;
238 Value::Value (FontStyle style
)
242 u
.fontstyle
= g_new (FontStyle
, 1);
243 u
.fontstyle
->style
= style
.style
;
247 Value::Value (FontSource source
)
250 k
= Type::FONTSOURCE
;
251 u
.fontsource
= g_new (FontSource
, 1);
252 u
.fontsource
->stream
= g_new (ManagedStreamCallbacks
, 1);
253 memcpy (u
.fontsource
->stream
, source
.stream
, sizeof (ManagedStreamCallbacks
));
257 Value::Value (PropertyPath propertypath
)
260 k
= Type::PROPERTYPATH
;
261 u
.propertypath
= g_new (PropertyPath
, 1);
262 u
.propertypath
->path
= g_strdup (propertypath
.path
);
263 u
.propertypath
->expanded_path
= g_strdup (propertypath
.expanded_path
);
264 u
.propertypath
->property
= propertypath
.property
;
268 Value::Value (Type::Kind kind
, void *npobj
)
272 u
.managed_object
= npobj
;
273 SetIsNull (npobj
== NULL
);
276 Value::Value (Point pt
)
280 u
.point
= g_new (Point
, 1);
281 *u
.point
= Point (pt
);
285 Value::Value (Uri uri
)
289 u
.uri
= g_new (Uri
, 1);
290 Uri::Copy (&uri
, u
.uri
);
294 Value::Value (Rect rect
)
298 u
.rect
= g_new (Rect
, 1);
299 *u
.rect
= Rect (rect
);
303 Value::Value (Size size
)
307 u
.size
= g_new (Size
, 1);
308 *u
.size
= Size (size
);
312 Value::Value (RepeatBehavior repeat
)
315 k
= Type::REPEATBEHAVIOR
;
316 u
.repeat
= g_new (RepeatBehavior
, 1);
317 *u
.repeat
= RepeatBehavior (repeat
);
321 Value::Value (Duration duration
)
325 u
.duration
= g_new (Duration
, 1);
326 *u
.duration
= Duration (duration
);
330 Value::Value (KeyTime keytime
)
334 u
.keytime
= g_new (KeyTime
, 1);
335 *u
.keytime
= KeyTime (keytime
);
339 Value::Value (const char *s
, bool take
)
344 u
.s
= take
? (char *) s
: g_strdup (s
);
345 SetIsNull (s
== NULL
);
348 Value::Value (GridLength grid_length
)
351 k
= Type::GRIDLENGTH
;
352 u
.grid_length
= g_new (GridLength
, 1);
353 *u
.grid_length
= GridLength (grid_length
);
357 Value::Value (Thickness thickness
)
361 u
.thickness
= g_new (Thickness
, 1);
362 *u
.thickness
= Thickness (thickness
);
366 Value::Value (CornerRadius corner
)
369 k
= Type::CORNERRADIUS
;
370 u
.corner
= g_new (CornerRadius
, 1);
371 *u
.corner
= CornerRadius (corner
);
375 Value::Value (ManagedTypeInfo type_info
)
378 k
= Type::MANAGEDTYPEINFO
;
379 u
.type_info
= g_new (ManagedTypeInfo
, 1);
380 *u
.type_info
= ManagedTypeInfo (type_info
);
385 Value::Copy (const Value
& v
)
391 SetIsNull (((Value
&)v
).GetIsNull());
393 /* make a copy of the string instead of just the pointer */
396 u
.s
= g_strdup (v
.u
.s
);
398 case Type::FONTFAMILY
:
399 if (v
.u
.fontfamily
) {
400 u
.fontfamily
= g_new (FontFamily
, 1);
401 u
.fontfamily
->source
= g_strdup (v
.u
.fontfamily
->source
);
404 case Type::FONTSOURCE
:
405 if (v
.u
.fontsource
) {
406 u
.fontsource
= g_new (FontSource
, 1);
407 u
.fontsource
->stream
= g_new (ManagedStreamCallbacks
, 1);
408 memcpy (u
.fontsource
->stream
, v
.u
.fontsource
->stream
, sizeof (ManagedStreamCallbacks
));
411 case Type::FONTWEIGHT
:
412 if (v
.u
.fontweight
) {
413 u
.fontweight
= g_new (FontWeight
, 1);
414 *u
.fontweight
= *v
.u
.fontweight
;
417 case Type::FONTSTRETCH
:
418 if (v
.u
.fontstretch
) {
419 u
.fontstretch
= g_new (FontStretch
, 1);
420 *u
.fontstretch
= *v
.u
.fontstretch
;
423 case Type::FONTSTYLE
:
425 u
.fontstyle
= g_new (FontStyle
, 1);
426 *u
.fontstyle
= *v
.u
.fontstyle
;
429 case Type::PROPERTYPATH
:
430 if (v
.u
.propertypath
) {
431 u
.propertypath
= g_new (PropertyPath
, 1);
432 u
.propertypath
->path
= g_strdup (v
.u
.propertypath
->path
);
433 u
.propertypath
->expanded_path
= g_strdup (v
.u
.propertypath
->expanded_path
);
434 u
.propertypath
->property
= v
.u
.propertypath
->property
;
439 u
.color
= g_new (Color
, 1);
440 *u
.color
= *v
.u
.color
;
445 u
.point
= g_new (Point
, 1);
446 *u
.point
= *v
.u
.point
;
451 u
.rect
= g_new (Rect
, 1);
457 u
.size
= g_new (Size
, 1);
463 u
.uri
= g_new (Uri
, 1);
464 Uri::Copy (v
.u
.uri
, u
.uri
);
469 case Type::REPEATBEHAVIOR
:
471 u
.repeat
= g_new (RepeatBehavior
, 1);
472 *u
.repeat
= *v
.u
.repeat
;
477 u
.duration
= g_new (Duration
, 1);
478 *u
.duration
= *v
.u
.duration
;
483 u
.keytime
= g_new (KeyTime
, 1);
484 *u
.keytime
= *v
.u
.keytime
;
487 case Type::GRIDLENGTH
:
488 if (v
.u
.grid_length
) {
489 u
.grid_length
= g_new (GridLength
, 1);
490 *u
.grid_length
= *v
.u
.grid_length
;
493 case Type::THICKNESS
:
495 u
.thickness
= g_new (Thickness
, 1);
496 *u
.thickness
= *v
.u
.thickness
;
499 case Type::CORNERRADIUS
:
501 u
.corner
= g_new (CornerRadius
, 1);
502 *u
.corner
= *v
.u
.corner
;
505 case Type::MANAGEDTYPEINFO
:
507 u
.type_info
= g_new (ManagedTypeInfo
, 1);
508 *u
.type_info
= *v
.u
.type_info
;
512 if (Is (Type::EVENTOBJECT
) && u
.dependency_object
) {
513 LOG_VALUE (" ref Value [%p] %s\n", this, GetName());
514 u
.dependency_object
->ref ();
523 switch (GetKind ()) {
530 case Type::FONTFAMILY
:
532 g_free (u
.fontfamily
->source
);
533 g_free (u
.fontfamily
);
536 case Type::FONTWEIGHT
:
537 g_free (u
.fontweight
);
539 case Type::FONTSTYLE
:
540 g_free (u
.fontstyle
);
542 case Type::FONTSTRETCH
:
543 g_free (u
.fontstretch
);
545 case Type::FONTSOURCE
:
547 g_free (u
.fontsource
->stream
);
548 g_free (u
.fontsource
);
551 case Type::PROPERTYPATH
:
552 if (u
.propertypath
) {
553 g_free (u
.propertypath
->path
);
554 g_free (u
.propertypath
->expanded_path
);
555 g_free (u
.propertypath
);
573 case Type::REPEATBEHAVIOR
:
582 case Type::GRIDLENGTH
:
583 g_free (u
.grid_length
);
585 case Type::THICKNESS
:
586 g_free (u
.thickness
);
588 case Type::CORNERRADIUS
:
592 if (Is (Type::EVENTOBJECT
) && u
.dependency_object
) {
593 LOG_VALUE ("unref Value [%p] %s\n", this, GetName());
594 u
.dependency_object
->unref ();
602 GString
*str
= g_string_new ("");
606 g_string_append_printf (str
, "{ %f }", u
.d
);
609 g_string_append (str
, u
.s
);
612 g_string_append_printf (str
, "{%g/%g/%g/%g}", u
.color
->r
, u
.color
->g
, u
.color
->b
, u
.color
->a
);
615 g_string_append_printf (str
, "{ %g, %g }", (u
.point
)->x
, (u
.point
)->y
);
618 g_string_append_printf (str
, "{ %g, %g }", (u
.size
)->width
, (u
.size
)->height
);
621 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
);
623 case Type::REPEATBEHAVIOR
:
624 if (u
.repeat
->IsForever ())
625 g_string_append (str
, "{repeat=forever}");
626 else if ((u
.repeat
)->HasDuration ())
627 g_string_append_printf (str
, "{repeat=duration}");
628 else if ((u
.repeat
)->HasCount ())
629 g_string_append_printf (str
, "{repeat=count %g}", (u
.repeat
)->GetCount ());
631 case Type::THICKNESS
:
632 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
);
635 g_string_append_printf (str
, "{duration/TODO}");
638 g_string_append_printf (str
, "{keytime/TODO}");
640 case Type::GRIDLENGTH
:
641 g_string_append_printf (str
, "{gridlength value:%.2f type:%d}", u
.grid_length
->val
, u
.grid_length
->type
);
644 if (Is (Type::EVENTOBJECT
) && u
.dependency_object
)
645 g_string_append_printf (str
, "[%s <%s>]", u
.dependency_object
->GetTypeName (), Is (Type::DEPENDENCY_OBJECT
) ? AsDependencyObject ()->GetName () : "no name");
647 g_string_append_printf (str
, "UnknownType");
651 return g_string_free (str
, FALSE
);
655 Value::operator!= (const Value
&v
) const
657 return !(*this == v
);
661 Value::operator== (const Value
&v
) const
666 if (padding
!= v
.padding
)
672 return v
.u
.s
== NULL
;
673 } else if (v
.u
.s
== NULL
)
676 return !strcmp (u
.s
, v
.u
.s
);
677 case Type::FONTFAMILY
:
678 return *u
.fontfamily
== *v
.u
.fontfamily
;
679 case Type::FONTWEIGHT
:
680 return *u
.fontweight
== *v
.u
.fontweight
;
681 case Type::FONTSTYLE
:
682 return *u
.fontstyle
== *v
.u
.fontstyle
;
683 case Type::FONTSTRETCH
:
684 return *u
.fontstretch
== *v
.u
.fontstretch
;
685 case Type::FONTSOURCE
:
686 if (u
.fontsource
&& v
.u
.fontsource
)
687 return u
.fontsource
->stream
->handle
== v
.u
.fontsource
->stream
->handle
;
688 return u
.fontsource
== v
.u
.fontsource
;
689 case Type::PROPERTYPATH
:
690 return *u
.propertypath
== *v
.u
.propertypath
;
692 return !memcmp (u
.color
, v
.u
.color
, sizeof (Color
));
694 return !memcmp (u
.point
, v
.u
.point
, sizeof (Point
));
696 return !memcmp (u
.rect
, v
.u
.rect
, sizeof (Rect
));
698 return !memcmp (u
.size
, v
.u
.size
, sizeof (Size
));
699 case Type::REPEATBEHAVIOR
:
700 // memcmp can't be used since the struct contains unassigned padding value
701 return *u
.repeat
== *v
.u
.repeat
;
703 // memcmp can't be used since the struct contains unassigned padding value
704 return *u
.duration
== *v
.u
.duration
;
706 // memcmp can't be used since the struct contains unassigned padding value
707 return *u
.keytime
== *v
.u
.keytime
;
708 case Type::GRIDLENGTH
:
709 return !memcmp (u
.grid_length
, v
.u
.grid_length
, sizeof (GridLength
));
710 case Type::THICKNESS
:
711 return !memcmp (u
.thickness
, v
.u
.thickness
, sizeof (Thickness
));
712 case Type::CORNERRADIUS
:
713 return !memcmp (u
.corner
, v
.u
.corner
, sizeof (CornerRadius
));
714 case Type::MANAGEDTYPEINFO
:
715 return !memcmp (u
.type_info
, v
.u
.type_info
, sizeof (ManagedTypeInfo
));
721 return *u
.uri
== *v
.u
.uri
;
722 case Type::MANAGED
: {
723 // If we avoid the cast to 64bit uint, i don't know how to implement this sanity check.
724 //g_return_val_if_fail (a == (a & 0xFFFFFFFF) && b == (b & 0xFFFFFFFF), false);
725 guint32 a
= GPOINTER_TO_INT (u
.managed_object
);
726 guint32 b
= GPOINTER_TO_INT (v
.u
.managed_object
);
727 return mono_gchandle_get_target (a
) == mono_gchandle_get_target (b
);
731 return !memcmp (&u
, &v
.u
, sizeof (u
));
738 Value::operator= (const Value
& other
)
746 // This is invoked by managed code to free the contents of the value
749 value_free_value (Value
* value
)
755 value_free_value2 (Value
*value
)
757 value_free_value (value
);
769 GString
*str
= g_string_new ("");
773 g_string_append_printf (str
, "DOUBLE");
776 g_string_append_printf (str
, "STRING");
779 g_string_append_printf (str
, "COLOR");
782 g_string_append_printf (str
, "POINT");
785 g_string_append_printf (str
, "SIZE");
788 g_string_append_printf (str
, "RECT");
790 case Type::REPEATBEHAVIOR
:
791 g_string_append_printf (str
, "REPEATBEHAVIOR");
793 case Type::THICKNESS
:
794 g_string_append_printf (str
, "THICKNESS");
797 g_string_append_printf (str
, "DURATION");
800 g_string_append_printf (str
, "KEYTIME");
802 case Type::GRIDLENGTH
:
803 g_string_append_printf (str
, "GRIDLENGTH");
806 if (u
.dependency_object
)
807 g_string_append_printf (str
, "[%s] [%p] %d", u
.dependency_object
->GetTypeName (), u
.dependency_object
, u
.dependency_object
->GetRefCount ());
809 g_string_append_printf (str
, "UnknownType");
813 return g_string_free (str
, FALSE
);