public static unsafe object ToObject (Type type, Value* value)
{
if (value == null || value->IsNull) {
return null;
}
if (value->IsGCHandle) {
IntPtr managed_object = value->u.p;
GCHandle handle = GCHandle.FromIntPtr (managed_object);
return handle.Target;
}
switch (value->k) {
case Kind.INVALID:
return null;
case Kind.DEPENDENCYPROPERTY:
return DependencyProperty.Lookup (value->u.p);
case Kind.BOOL:
return value->u.i32 != 0;
case Kind.DOUBLE:
return value->u.d;
case Kind.FLOAT:
return value->u.f;
case Kind.UINT64:
return value->u.ui64;
case Kind.INT64:
return value->u.i64;
case Kind.TIMESPAN:
return new TimeSpan (value->u.i64);
case Kind.CURSORTYPE:
return Cursors.FromEnum ((CursorType) value->u.i32);
case Kind.TEXTDECORATIONS:
return (value->u.i32 == (int) TextDecorationKind.Underline) ? TextDecorations.Underline : null;
case Kind.INT32:
return value->u.i32;
case Kind.CHAR:
return (char) value->u.ui32;
case Kind.SURFACE:
return NativeDependencyObjectHelper.FromIntPtr (value->u.p);
case Kind.STRING: {
string str = Marshal.PtrToStringAuto (value->u.p);
if (type == null)
return str;
// marshall back to the .NET type that we simply serialised as 'string' for unmanaged usage
if (type == typeof (System.Windows.Markup.XmlLanguage))
return XmlLanguage.GetLanguage (str);
else
return str;
}
case Kind.URI: {
UnmanagedUri *uri = (UnmanagedUri*)value->u.p;
return uri->originalString == IntPtr.Zero
? new Uri("", UriKind.Relative)
: new Uri (Marshal.PtrToStringAuto (uri->originalString),
uri->isAbsolute ? UriKind.Absolute : UriKind.Relative);
}
case Kind.XMLLANGUAGE: {
string str = Marshal.PtrToStringAuto (value->u.p);
return XmlLanguage.GetLanguage (str);
}
case Kind.FONTFAMILY: {
UnmanagedFontFamily *family = (UnmanagedFontFamily*)value->u.p;
return new FontFamily (family == null ? null : Marshal.PtrToStringAuto (family->source));
}
case Kind.FONTSTRETCH: {
UnmanagedFontStretch *stretch = (UnmanagedFontStretch*)value->u.p;
return new FontStretch (stretch == null ? FontStretchKind.Normal : stretch->stretch);
}
case Kind.FONTSTYLE: {
UnmanagedFontStyle *style = (UnmanagedFontStyle*)value->u.p;
return new FontStyle (style == null ? FontStyleKind.Normal : style->style);
}
case Kind.FONTWEIGHT: {
UnmanagedFontWeight *weight = (UnmanagedFontWeight*)value->u.p;
return new FontWeight (weight == null ? FontWeightKind.Normal : weight->weight);
}
case Kind.FONTSOURCE: {
UnmanagedFontSource *fs = (UnmanagedFontSource *) value->u.p;
ManagedStreamCallbacks callbacks;
GlyphTypeface typeface;
StreamWrapper wrapper;
switch (fs->type) {
case FontSourceType.ManagedStream:
callbacks = (ManagedStreamCallbacks) Marshal.PtrToStructure (fs->source.stream, typeof (ManagedStreamCallbacks));
wrapper = (StreamWrapper) GCHandle.FromIntPtr (callbacks.handle).Target;
return new FontSource (wrapper.stream);
case FontSourceType.GlyphTypeface:
typeface = new GlyphTypeface (fs->source.typeface);
return new FontSource (typeface);
default:
throw new Exception (String.Format ("Do not know how to create a FontSource of type {0}",
fs->type.ToString ()));
}
}
case Kind.GLYPHTYPEFACE: {
return new GlyphTypeface (value->u.p);
}
case Kind.PROPERTYPATH: {
UnmanagedPropertyPath *propertypath = (UnmanagedPropertyPath *) value->u.p;
if (propertypath == null)
return new PropertyPath (null);
if (propertypath->property != IntPtr.Zero)
return null;
return new PropertyPath (Marshal.PtrToStringAuto (propertypath->pathString));
}
case Kind.POINT: {
Point *point = (Point*)value->u.p;
return (point == null) ? new Point (0,0) : *point;
}
case Kind.RECT: {
Rect *rect = (Rect*)value->u.p;
return (rect == null) ? new Rect (0,0,0,0) : *rect;
}
case Kind.SIZE: {
Size *size = (Size*)value->u.p;
return (size == null) ? new Size (0,0) : *size;
}
case Kind.CORNERRADIUS: {
CornerRadius *corner = (CornerRadius*)value->u.p;
return (corner == null) ? new CornerRadius (0) : *corner;
}
case Kind.AUDIOFORMAT: {
UnmanagedAudioFormat *format = (UnmanagedAudioFormat*)value->u.p;
return (format == null) ? new AudioFormat () : format->ToAudioFormat ();
}
case Kind.VIDEOFORMAT: {
UnmanagedVideoFormat *format = (UnmanagedVideoFormat*)value->u.p;
return (format == null) ? new VideoFormat () : format->ToVideoFormat ();
}
case Kind.THICKNESS: {
Thickness *thickness = (Thickness*)value->u.p;
return (thickness == null) ? new Thickness (0) : *thickness;
}
case Kind.COLOR: {
UnmanagedColor *color = (UnmanagedColor*)value->u.p;
if (color == null)
return new Color ();
return color->ToColor ();
}
case Kind.MATRIX:
case Kind.UNMANAGEDMATRIX: {
return new Matrix (value->u.p);
}
case Kind.MATRIX3D:
case Kind.UNMANAGEDMATRIX3D: {
return new Matrix3D (value->u.p);
}
case Kind.STYLUSPOINT:
case Kind.UNMANAGEDSTYLUSPOINT: {
var kind = value->k;
var ptr = value->u.p;
var x = (double) Value.ToObject (typeof (double), NativeMethods.dependency_object_get_value (ptr, kind, UnmanagedStylusPoint.XProperty.Native));
var y = (double) Value.ToObject (typeof (double), NativeMethods.dependency_object_get_value (ptr, kind, UnmanagedStylusPoint.YProperty.Native));
var pressure = (double) Value.ToObject (typeof (double), NativeMethods.dependency_object_get_value (ptr, kind, UnmanagedStylusPoint.PressureFactorProperty.Native));
return new StylusPoint { X = x, Y = y, PressureFactor = (float) pressure };
}
case Kind.DURATION: {
Duration* duration = (Duration*)value->u.p;
return (duration == null) ? Duration.Automatic : *duration;
}
case Kind.KEYTIME: {
KeyTime* keytime = (KeyTime*)value->u.p;
return (keytime == null) ? KeyTime.FromTimeSpan (TimeSpan.Zero) : *keytime;
}
case Kind.GRIDLENGTH: {
GridLength* gridlength = (GridLength*)value->u.p;
return (gridlength == null) ? new GridLength () : *gridlength;
}
case Kind.REPEATBEHAVIOR: {
RepeatBehavior *repeat = (RepeatBehavior*)value->u.p;
return (repeat == null) ? new RepeatBehavior () : *repeat;
}
case Kind.MEDIAATTRIBUTE_COLLECTION: {
MediaAttributeCollection attrs = (MediaAttributeCollection) NativeDependencyObjectHelper.Lookup (value->k, value->u.p);
return attrs.AsDictionary ();
}
case Kind.MANAGEDTYPEINFO: {
ManagedTypeInfo *type_info = (ManagedTypeInfo *) value->u.p;
if (type_info == null)
return null;
return Deployment.Current.Types.KindToType (type_info->Kind);
}
default:
Type tt = Deployment.Current.Types.KindToType (value->k);
if (tt != null && tt.IsEnum)
return Enum.ToObject (tt, value->u.i32);
break;
}
if (NativeMethods.type_is_dependency_object (value->k)){
if (value->u.p == IntPtr.Zero)
return null;
return NativeDependencyObjectHelper.Lookup (value->k, value->u.p);
}
throw new Exception (String.Format ("Do not know how to convert {0} {1}. Managed type: {2}",
value->k, (int) value->k, Deployment.Current.Types.KindToType (value->k)));
}