示例#1
0
文件: Value.cs 项目: shana/moon
		//
		// 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 {
				// 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;
		}