Exemplo n.º 1
0
        /// <summary>
        /// Connects a callback function (<paramref name="callback"/>) to a signal on this object.
        /// </summary>
        /// <remarks>
        /// The callback will be triggered every time this signal is issued on this instance.
        /// </remarks>
        /// <param name="detailedSignal">A string of the form "signal-name::detail".</param>
        /// <param name="callback">The callback to connect.</param>
        /// <param name="data">Data to pass to handler calls.</param>
        /// <returns>The handler id.</returns>
        /// <exception cref="T:System.Exception">If it failed to connect the signal.</exception>
        public uint SignalConnect(string detailedSignal, Delegate callback, IntPtr data = default)
        {
            if (callback is Image.EvalDelegate evalDelegate)
            {
                void EvalMarshal(IntPtr imagePtr, IntPtr progressPtr, IntPtr userDataPtr)
                {
                    if (progressPtr == IntPtr.Zero || imagePtr == IntPtr.Zero)
                    {
                        return;
                    }

                    using var image = new Image(imagePtr);
                    image.ObjectRef();

                    var progressStruct = progressPtr.Dereference <VipsProgress>();

                    evalDelegate.Invoke(image, progressStruct);
                }

                callback = (VipsImage.EvalSignal)EvalMarshal;
            }

            // add a weak reference callback to ensure all handles are released on finalization
            if (_handles.Count == 0)
            {
                GWeakNotify notify       = ReleaseDelegates;
                var         notifyHandle = GCHandle.Alloc(notify);

                Internal.GObject.WeakRef(this, notify, GCHandle.ToIntPtr(notifyHandle));
            }

            // prevent the delegate from being re-located or disposed of by the garbage collector
            var delegateHandle = GCHandle.Alloc(callback);

            _handles.Add(delegateHandle);

            // get the pointer for the delegate which can be passed to the native code
            var callbackPtr = Marshal.GetFunctionPointerForDelegate(callback);
            var ret         = GSignal.ConnectData(this, detailedSignal, callbackPtr, data, null, default);

            if (ret == 0)
            {
                throw new Exception("Failed to connect signal.");
            }

            return(ret);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get the contents of a GValue.
        /// </summary>
        /// <remarks>
        /// The contents of the GValue are read out as a C# type.
        /// </remarks>
        /// <returns></returns>
        public object Get()
        {
            // logger.Debug($"Get: this = {this}");
            var gtype       = GetTypeOf();
            var fundamental = GType.GTypeFundamental(gtype);

            object result;

            if (gtype == GBoolType)
            {
                result = Internal.GValue.GValueGetBoolean(ref Struct) != 0;
            }
            else if (gtype == GIntType)
            {
                result = Internal.GValue.GValueGetInt(ref Struct);
            }
            else if (gtype == GDoubleType)
            {
                result = Internal.GValue.GValueGetDouble(ref Struct);
            }
            else if (fundamental == GEnumType)
            {
                result = FromEnum(gtype, Internal.GValue.GValueGetEnum(ref Struct));
            }
            else if (fundamental == GFlagsType)
            {
                result = Internal.GValue.GValueGetFlags(ref Struct);
            }
            else if (gtype == GStrType)
            {
                result = Internal.GValue.GValueGetString(ref Struct).ToUtf8String();
            }
            else if (gtype == RefStrType)
            {
                // don't bother getting the size -- assume these are always
                // null-terminated C strings
                ulong psize = 0;
                result = VipsType.VipsValueGetRefString(ref Struct, ref psize).ToUtf8String();
            }
            else if (gtype == ImageType)
            {
                // GValueGetObject() will not add a ref ... that is
                // held by the gvalue
                var vi = Internal.GObject.GValueGetObject(ref Struct);

                // we want a ref that will last with the life of the vimage:
                // this ref is matched by the unref that's attached to finalize
                // by GObject
                var image = new Image(vi);
                image.ObjectRef();

                result = image;
            }
            else if (gtype == ArrayIntType)
            {
                var psize  = 0;
                var intPtr = VipsType.VipsValueGetArrayInt(ref Struct, ref psize);

                var intArr = new int[psize];
                Marshal.Copy(intPtr, intArr, 0, psize);
                result = intArr;
            }
            else if (gtype == ArrayDoubleType)
            {
                var psize  = 0;
                var intPtr = VipsType.VipsValueGetArrayDouble(ref Struct, ref psize);

                var doubleArr = new double[psize];
                Marshal.Copy(intPtr, doubleArr, 0, psize);
                result = doubleArr;
            }
            else if (gtype == ArrayImageType)
            {
                var psize  = 0;
                var ptrArr = VipsImage.VipsValueGetArrayImage(ref Struct, ref psize);

                var images = new Image[psize];
                for (var i = 0; i < psize; i++)
                {
                    var vi = Marshal.ReadIntPtr(ptrArr, i * IntPtr.Size);
                    images[i] = new Image(vi);
                    images[i].ObjectRef();
                }

                result = images;
            }
            else if (gtype == BlobType)
            {
                ulong psize = 0;
                var   array = VipsType.VipsValueGetBlob(ref Struct, ref psize);

                // Blob types are returned as an array of bytes.
                var byteArr = new byte[psize];
                Marshal.Copy(array, byteArr, 0, (int)psize);
                result = byteArr;
            }
            else
            {
                throw new Exception($"unsupported gtype for get {Base.TypeName(gtype)}");
            }

            return(result);
        }
Exemplo n.º 3
0
 /// <summary>
 /// Make a <see cref="MutableImage"/> from a regular copied <see cref="Image"/>.
 /// </summary>
 /// <remarks>
 /// This is for internal use only. See <see cref="Image.Mutate"/> for the
 /// user-facing interface.
 /// </remarks>
 internal MutableImage(Image copiedImage) : base(copiedImage.ObjectRef())
 {
     Image = copiedImage;
 }