// // How do we support "null" values, should the caller take care of that? // // The caller is responsible for calling value_free_value on the returned Value public static Value FromObject(object v, bool box_value_types) { Value value = new Value(); unsafe { if (box_value_types && (v is ValueType || v is string)) { value.boxed_valuetype = GCHandle.Alloc(v); } 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.Kind = dov.GetKind(); value.u.p = dov.NativeHandle; } else if (v is DependencyProperty) { value.Kind = Kind.DEPENDENCYPROPERTY; value.u.p = ((DependencyProperty)v).Native; } else if (v is int || (v.GetType().IsEnum&& Enum.GetUnderlyingType(v.GetType()) == typeof(int))) { value.Kind = Deployment.Current.Types.TypeToKind(v.GetType()); value.u.i32 = (int)v; } else if (v is byte || (v.GetType().IsEnum&& Enum.GetUnderlyingType(v.GetType()) == typeof(byte))) { value.Kind = Deployment.Current.Types.TypeToKind(v.GetType()); value.u.i32 = (byte)v; } else if (v is bool) { value.Kind = Kind.BOOL; value.u.i32 = ((bool)v) ? 1 : 0; } else if (v is double) { value.Kind = Kind.DOUBLE; value.u.d = (double)v; } else if (v is float) { value.Kind = Kind.FLOAT; value.u.f = (float)v; } else if (v is long) { value.Kind = Kind.INT64; value.u.i64 = (long)v; } else if (v is TimeSpan) { TimeSpan ts = (TimeSpan)v; value.Kind = Kind.TIMESPAN; value.u.i64 = ts.Ticks; } else if (v is ulong) { value.Kind = Kind.UINT64; value.u.ui64 = (ulong)v; } else if (v is uint) { value.Kind = Kind.UINT32; value.u.ui32 = (uint)v; } else if (v is char) { value.Kind = Kind.CHAR; value.u.ui32 = (uint)(char)v; } else if (v is string) { value.Kind = Kind.STRING; value.u.p = StringToIntPtr((string)v); } else if (v is Rect) { Rect rect = (Rect)v; value.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = 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); upp->expandedPathString = StringToIntPtr(propertypath.ExpandedPath); } else { upp->pathString = IntPtr.Zero; upp->expandedPathString = IntPtr.Zero; } } else if (v is Uri) { Uri uri = (Uri)v; value.Kind = Kind.URI; value.u.p = UriHelper.ToNativeUri(uri); } else if (v is XmlLanguage) { XmlLanguage lang = (XmlLanguage)v; value.Kind = Kind.XMLLANGUAGE; value.u.p = StringToIntPtr(lang.IetfLanguageTag); } else if (v is Cursor) { Cursor c = (Cursor)v; value.Kind = Kind.CURSORTYPE; value.u.i32 = (int)c.cursor; } else if (v is GridLength) { GridLength gl = (GridLength)v; value.Kind = 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.Kind = 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.Kind = 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.Kind = 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.Kind = Kind.TEXTDECORATIONS; value.u.i32 = (int)(v as TextDecorationCollection).Kind; } else if (v is Type) { Type t = v as Type; value.Kind = Kind.MANAGEDTYPEINFO; value.u.p = NativeMethods.managed_type_info_new(Deployment.Current.Types.TypeToKind(t)); } else if (v is Value) { throw new InvalidOperationException("You can not create a Mono.Value from a Mono.Value."); } 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.Kind = Deployment.Current.Types.TypeToKind(v.GetType()); value.u.p = GCHandle.ToIntPtr(handle); } } return(value); }
public static unsafe object ToObject(Type type, Value *value) { if (value == null || value->IsNull) { return(null); } if (value->boxed_valuetype.IsAllocated) { return(value->boxed_valuetype.Target); } if (value->IsGCHandle) { IntPtr managed_object = value->u.p; GCHandle handle = GCHandle.FromIntPtr(managed_object); return(handle.Target); } switch (value->Kind) { 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.UINT32: return(value->u.ui32); case Kind.CHAR: return((char)value->u.ui32); case Kind.SURFACE: return(NativeDependencyObjectHelper.FromIntPtr(value->u.p)); case Kind.STRING: { return(Marshal.PtrToStringAuto(value->u.p)); } case Kind.URI: return(UriHelper.FromNativeUri(value->u.p)); 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), Marshal.PtrToStringAuto(propertypath->expandedPathString))); } 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->Kind; var ptr = value->u.p; var x = (double)Value.ToObject(typeof(double), NativeMethods.dependency_object_get_value(ptr, UnmanagedStylusPoint.XProperty.Native)); var y = (double)Value.ToObject(typeof(double), NativeMethods.dependency_object_get_value(ptr, UnmanagedStylusPoint.YProperty.Native)); var pressure = (double)Value.ToObject(typeof(double), NativeMethods.dependency_object_get_value(ptr, 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: { IntPtr p = value->u.p; if (p == IntPtr.Zero) { return(null); } int count = NativeMethods.collection_get_count(p); var dict = new Dictionary <string, string> (); for (int i = 0; i < count; i++) { IntPtr map = NativeMethods.collection_get_value_at(p, i); if (map == IntPtr.Zero) { continue; } Value *attribute = (Value *)map; if (attribute->Kind != Kind.MEDIAATTRIBUTE || attribute->u.p == IntPtr.Zero) { continue; } string name = NativeMethods.media_attribute_get_name(attribute->u.p); string val = NativeMethods.media_attribute_get_value(attribute->u.p); dict.Add(name, val); } return(dict); } 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->Kind); if (tt != null && tt.IsEnum) { return(Enum.ToObject(tt, value->u.i32)); } break; } if (NativeMethods.type_is_event_object(value->Kind)) { if (value->u.p == IntPtr.Zero) { return(null); } return(NativeDependencyObjectHelper.Lookup(value->u.p)); } throw new Exception(String.Format("Do not know how to convert {0} {1}. Managed type: {2}", value->Kind, (int)value->Kind, Deployment.Current.Types.KindToType(value->Kind))); }