public static Value FromObject (object v, bool box_value_types)
{
Value value = new Value ();
unsafe {
// get rid of this case right away.
if (box_value_types && v.GetType().IsValueType) {
//Console.WriteLine ("Boxing a value of type {0}:", v.GetType());
GCHandle handle = GCHandle.Alloc (v);
value.k = Deployment.Current.Types.TypeToKind (v.GetType ());
value.IsGCHandle = true;
value.u.p = GCHandle.ToIntPtr (handle);
return value;
}
if (v is IEasingFunction && !(v is EasingFunctionBase))
v = new EasingFunctionWrapper (v as IEasingFunction);
if (v is INativeEventObjectWrapper) {
INativeEventObjectWrapper dov = (INativeEventObjectWrapper) v;
if (dov.NativeHandle == IntPtr.Zero)
throw new Exception (String.Format (
"Object {0} has not set its native property", dov.GetType()));
NativeMethods.event_object_ref (dov.NativeHandle);
value.k = dov.GetKind ();
value.u.p = dov.NativeHandle;
} else if (v is DependencyProperty) {
value.k = Kind.DEPENDENCYPROPERTY;
value.u.p = ((DependencyProperty)v).Native;
}
else if (v is int || (v.GetType ().IsEnum && Enum.GetUnderlyingType (v.GetType()) == typeof(int))) {
value.k = Deployment.Current.Types.TypeToKind (v.GetType ());
value.u.i32 = (int) v;
}
else if (v is bool) {
value.k = Kind.BOOL;
value.u.i32 = ((bool) v) ? 1 : 0;
}
else if (v is double) {
value.k = Kind.DOUBLE;
value.u.d = (double) v;
}
else if (v is float) {
value.k = Kind.FLOAT;
value.u.f = (float) v;
}
else if (v is long) {
value.k = Kind.INT64;
value.u.i64 = (long) v;
}
else if (v is TimeSpan) {
TimeSpan ts = (TimeSpan) v;
value.k = Kind.TIMESPAN;
value.u.i64 = ts.Ticks;
}
else if (v is ulong) {
value.k = Kind.UINT64;
value.u.ui64 = (ulong) v;
}
else if (v is uint) {
value.k = Kind.UINT32;
value.u.ui32 = (uint) v;
}
else if (v is char) {
value.k = Kind.CHAR;
value.u.ui32 = (uint) (char) v;
}
else if (v is string) {
value.k = Kind.STRING;
value.u.p = StringToIntPtr ((string) v);
}
else if (v is Rect) {
Rect rect = (Rect) v;
value.k = Kind.RECT;
value.u.p = Marshal.AllocHGlobal (sizeof (Rect));
Marshal.StructureToPtr (rect, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is Size) {
Size size = (Size) v;
value.k = Kind.SIZE;
value.u.p = Marshal.AllocHGlobal (sizeof (Size));
Marshal.StructureToPtr (size, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is CornerRadius) {
CornerRadius corner = (CornerRadius) v;
value.k = Kind.CORNERRADIUS;
value.u.p = Marshal.AllocHGlobal (sizeof (CornerRadius));
Marshal.StructureToPtr (corner, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is AudioFormat) {
AudioFormat f = (AudioFormat) v;
value.k = Kind.AUDIOFORMAT;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedAudioFormat));
UnmanagedAudioFormat *format = (UnmanagedAudioFormat*) value.u.p;
format->bitsPerSample = f.BitsPerSample;
format->channels = f.Channels;
format->samplesPerSecond = f.SamplesPerSecond;
format->waveFormat = f.WaveFormat;
}
else if (v is VideoFormat) {
VideoFormat f = (VideoFormat) v;
value.k = Kind.VIDEOFORMAT;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedVideoFormat));
UnmanagedVideoFormat *format = (UnmanagedVideoFormat*) value.u.p;
format->framesPerSecond = f.FramesPerSecond;
format->height = f.PixelHeight;
format->width = f.PixelWidth;
format->stride = f.Stride;
format->pixelFormat = f.PixelFormat;
}
else if (v is Point) {
Point pnt = (Point) v;
value.k = Kind.POINT;
value.u.p = Marshal.AllocHGlobal (sizeof (Point));
Marshal.StructureToPtr (pnt, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is Thickness) {
Thickness thickness = (Thickness)v;
value.k = Kind.THICKNESS;
value.u.p = Marshal.AllocHGlobal (sizeof (Thickness));
Marshal.StructureToPtr (thickness, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is Color) {
Color c = (Color) v;
value.k = Kind.COLOR;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedColor));
UnmanagedColor* color = (UnmanagedColor*) value.u.p;
color->r = c.R / 255.0f;
color->g = c.G / 255.0f;
color->b = c.B / 255.0f;
color->a = c.A / 255.0f;
}
else if (v is Matrix) {
// hack around the fact that managed Matrix is a struct while unmanaged Matrix is a DO
// i.e. the unmanaged and managed structure layouts ARE NOT equal
return FromObject (new UnmanagedMatrix ((Matrix) v), box_value_types);
}
else if (v is StylusPoint) {
return FromObject (new UnmanagedStylusPoint ((StylusPoint) v), box_value_types);
}
else if (v is Matrix3D) {
// hack around the fact that managed Matrix3D is a struct while unmanaged Matrix3D is a DO
// i.e. the unmanaged and managed structure layouts ARE NOT equal
return FromObject (new UnmanagedMatrix3D ((Matrix3D) v), box_value_types);
}
else if (v is Duration) {
Duration d = (Duration) v;
value.k = Kind.DURATION;
value.u.p = Marshal.AllocHGlobal (sizeof (Duration));
Marshal.StructureToPtr (d, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is KeyTime) {
KeyTime k = (KeyTime) v;
value.k = Kind.KEYTIME;
value.u.p = Marshal.AllocHGlobal (sizeof (KeyTime));
Marshal.StructureToPtr (k, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is RepeatBehavior) {
RepeatBehavior d = (RepeatBehavior) v;
value.k = Kind.REPEATBEHAVIOR;
value.u.p = Marshal.AllocHGlobal (sizeof (RepeatBehavior));
Marshal.StructureToPtr (d, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is FontFamily) {
FontFamily family = (FontFamily) v;
value.k = Kind.FONTFAMILY;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontFamily));
Marshal.StructureToPtr (family, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is FontSource) {
FontSource source = (FontSource) v;
value.k = Kind.FONTSOURCE;
if (source.wrapper != null || source.typeface != null) {
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontSource));
UnmanagedFontSource *ufs = (UnmanagedFontSource *) value.u.p;
ufs->type = source.type;
switch (source.type) {
case FontSourceType.ManagedStream:
ManagedStreamCallbacks callbacks = source.wrapper.GetCallbacks ();
ufs->source.stream = Marshal.AllocHGlobal (sizeof (UnmanagedStreamCallbacks));
Marshal.StructureToPtr (callbacks, ufs->source.stream, false);
break;
case FontSourceType.GlyphTypeface:
ufs->source.typeface = source.typeface.Native;
break;
}
} else {
value.IsNull = true;
}
}
else if (v is PropertyPath) {
PropertyPath propertypath = (PropertyPath) v;
value.k = Kind.PROPERTYPATH;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedPropertyPath));
UnmanagedPropertyPath *upp = (UnmanagedPropertyPath *) value.u.p;
upp->property = propertypath.NativeDP;
if (upp->property == IntPtr.Zero)
upp->pathString = StringToIntPtr (propertypath.Path);
else
upp->pathString = IntPtr.Zero;
upp->expandedPathString = IntPtr.Zero;
}
else if (v is Uri) {
Uri uri = (Uri) v;
value.k = Kind.URI;
value.u.p = UnmanagedUri.FromUri (uri);
}
else if (v is XmlLanguage) {
XmlLanguage lang = (XmlLanguage) v;
value.k = Kind.STRING;
value.u.p = StringToIntPtr (lang.IetfLanguageTag);
}
else if (v is Cursor) {
Cursor c = (Cursor) v;
value.k = Kind.CURSORTYPE;
value.u.i32 = (int)c.cursor;
}
else if (v is GridLength) {
GridLength gl = (GridLength) v;
value.k = Kind.GRIDLENGTH;
value.u.p = Marshal.AllocHGlobal (sizeof (GridLength));
Marshal.StructureToPtr (gl, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is FontStretch) {
FontStretch stretch = (FontStretch) v;
value.k = Kind.FONTSTRETCH;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontStretch));
Marshal.StructureToPtr (stretch, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is FontStyle) {
FontStyle style = (FontStyle) v;
value.k = Kind.FONTSTYLE;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontStyle));
Marshal.StructureToPtr (style, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is FontWeight) {
FontWeight weight = (FontWeight) v;
value.k = Kind.FONTWEIGHT;
value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontWeight));
Marshal.StructureToPtr (weight, value.u.p, false); // Unmanaged and managed structure layout is equal.
}
else if (v is TextDecorationCollection) {
value.k = Kind.TEXTDECORATIONS;
value.u.i32 = (int) (v as TextDecorationCollection).Kind;
}
else if (v is Type) {
Type t = v as Type;
ManagedTypeInfo mti = new ManagedTypeInfo ();
mti.full_name = StringToIntPtr (t.FullName);
mti.Kind = Deployment.Current.Types.TypeToKind (t);
value.k = Kind.MANAGEDTYPEINFO;
value.u.p = Marshal.AllocHGlobal (sizeof (ManagedTypeInfo));
Marshal.StructureToPtr (mti, value.u.p, false);
}
else {
//Console.WriteLine ("Do not know how to encode {0} yet, boxing it", v.GetType ());
// TODO: We probably need to marshal types that can animate as the
// corresponding type (Point, Double, Color, etc).
// TODO: We need to store the GCHandle somewhere so that we can free it,
// or register a callback on the surface for the unmanaged code to call.
GCHandle handle = GCHandle.Alloc (v);
value.IsGCHandle = true;
value.k = Deployment.Current.Types.TypeToKind (v.GetType ());
value.u.p = GCHandle.ToIntPtr (handle);
}
}
return value;
}