Exemple #1
0
        /// <summary>
        /// Gets whether a non-padded contiguous span of pixels
        /// can be created over the underlying memory.
        /// </summary>
        /// <remarks>
        /// To include padding use <see cref="IsPaddedPixelContiguous"/>
        /// </remarks>
        public static bool IsPixelContiguous(this IReadOnlyPixelMemory buffer)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            return(buffer.Width * buffer.ElementSize == buffer.ByteStride);
        }
Exemple #2
0
        public static ReadOnlySpan <TPixel> GetPixelSpan <TPixel>(
            this IReadOnlyPixelMemory <TPixel> buffer, int start)
            where TPixel : unmanaged, IPixel
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            return(buffer.GetPixelSpan()[start..]);
Exemple #3
0
        public static int GetPixelStride(this IReadOnlyPixelMemory buffer)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (!buffer.IsPaddedPixelContiguous())
            {
                throw new InvalidOperationException("The buffer is not pixel-contiguous.");
            }

            return(buffer.ByteStride / buffer.ElementSize);
        }
        private static unsafe MouseCursor PlatformFromPixels(
            IReadOnlyPixelMemory <Color> data, int width, int height, Point origin)
        {
            var iconInfo = new IconInfo();

            // bitmaps can not be constructed from Rgba directly
            using (var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb))
            {
                var rect    = new System.Drawing.Rectangle(0, 0, width, height);
                var bmpData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

                try
                {
                    var source      = data.GetPixelSpan();
                    int pixelStride = data.GetPixelStride();
                    for (int y = 0; y < bmpData.Height; y++)
                    {
                        var srcRow = source.Slice(y * pixelStride, width);
                        var dstRow = new Span <Bgra32>((byte *)bmpData.Scan0 + y * bmpData.Stride, bmpData.Width);

                        for (int x = 0; x < srcRow.Length; x++)
                        {
                            dstRow[x].FromColor(srcRow[x]);
                        }
                    }
                }
                finally
                {
                    bitmap.UnlockBits(bmpData);
                }

                GetIconInfo(bitmap.GetHicon(), ref iconInfo);
            }

            iconInfo.xHotspot = origin.X;
            iconInfo.yHotspot = origin.Y;
            iconInfo.fIcon    = false;

            var cursor = new Cursor(CreateIconIndirect(iconInfo));

            return(new MouseCursor(cursor, needsDisposing: true));
        }
Exemple #5
0
        /// <summary>
        /// Creates a mouse cursor from the specified pixels.
        /// </summary>
        /// <param name="pixels">Pixels to use as the cursor image.</param>
        /// <param name="origin">A point in the pixels that is used as the cursor position.</param>
        /// <param name="sourceRectangle">Optional part of the image to use as the cursor.</param>
        public static MouseCursor FromPixels(
            IReadOnlyPixelRows pixels, Point origin, Rectangle?sourceRectangle = null)
        {
            if (pixels == null)
            {
                throw new ArgumentNullException(nameof(pixels));
            }

            Rectangle rect = sourceRectangle ?? pixels.GetBounds();

            if (!pixels.GetBounds().Contains(rect))
            {
                throw new ArgumentOutOfRangeException(
                          nameof(sourceRectangle), "The source rectangle is outside the pixel buffer.");
            }

            IReadOnlyPixelMemory <Color>?pixelBuffer = null;

            try
            {
                if (rect.Position == Point.Zero &&
                    pixels is IReadOnlyPixelMemory <Color> rgbaMemory &&
                    rgbaMemory.IsPaddedPixelContiguous())
                {
                    pixelBuffer = rgbaMemory;
                }
                else
                {
                    pixelBuffer = Image.LoadPixels <Color>(pixels.ProjectRows(x => x.Crop(rect)));
                }

                return(PlatformFromPixels(pixelBuffer, rect.Width, rect.Height, origin));
            }
            finally
            {
                pixelBuffer?.Dispose();
            }
        }
        private static unsafe MouseCursor PlatformFromPixels(
            IReadOnlyPixelMemory <Color> data, int width, int height, Point origin)
        {
            var surface = IntPtr.Zero;
            var handle  = IntPtr.Zero;

            try
            {
                fixed(Color *ptr = data.GetPixelSpan())
                {
                    surface = SDL.CreateRGBSurfaceFrom(
                        (IntPtr)ptr, width, height, 32, data.ByteStride,
                        0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
                }

                if (surface == IntPtr.Zero)
                {
                    throw new InvalidOperationException(
                              "Failed to create surface for mouse cursor.", new Exception(SDL.GetError()));
                }

                handle = SDL.Mouse.CreateColorCursor(surface, origin.X, origin.Y);
                if (handle == IntPtr.Zero)
                {
                    throw new InvalidOperationException(
                              "Failed to create mouse cursor from surface.", new Exception(SDL.GetError()));
                }
            }
            finally
            {
                if (surface != IntPtr.Zero)
                {
                    SDL.FreeSurface(surface);
                }
            }
            return(new MouseCursor(handle));
        }