// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using SkiaSharp; namespace Iot.Device.Graphics.SkiaSharpAdapter { /// /// Contains extension methods that operate on /// public static class SkiaSharpGraphicsExtensions { /// /// Resizes an image. Extension method for SkiaSharp /// /// The image to resize /// The new size /// A new image. The old image is unaffected /// The image is not a SkiaSharpBitmap, meaning more than one image connector is in scope public static BitmapImage Resize(this BitmapImage image, Size size) { if (image is SkiaSharpBitmap img) { var resized = img.WrappedBitmap.Resize(new SKSizeI(size.Width, size.Height), SKFilterQuality.Medium); return new SkiaSharpBitmap(resized, image.PixelFormat); } throw new NotSupportedException("This overload can only Resize SkiaSharpImage instances"); } /// /// Draws text to the bitmap /// public static void DrawText(this IGraphics graphics, string text, string fontFamilyName, int size, Color color, Point position) { var canvas = GetCanvas(graphics); SKFont fnt = new SKFont(SKTypeface.FromFamilyName(fontFamilyName), size); var paint = new SKPaint(fnt); paint.Color = new SKColor((uint)color.ToArgb()); paint.TextAlign = SKTextAlign.Left; paint.TextEncoding = SKTextEncoding.Utf16; int lineSpacing = size + 2; SKPoint currentPosition = new SKPoint(position.X, position.Y + size); // drawing begins to the right and above the given point. var texts = text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()); // The DrawText implementation of SkiaSharp does not work with line breaks, so do that manually. foreach (var t in texts) { canvas.DrawText(t, currentPosition, paint); currentPosition.Y += lineSpacing; } } /// /// Draws another image into this one, at the given position and without scaling /// /// The target bitmap /// The source bitmap /// The x coordinate of the source bitmap in the resulting target bitmap /// The y coordinate of the source bitmap in the resulting target bitmap public static void DrawImage(this IGraphics graphics, BitmapImage source, int x, int y) { var sourceBmp = (SkiaSharpBitmap)source; var targetCanvas = GetCanvas(graphics); targetCanvas.DrawBitmap(sourceBmp.WrappedBitmap, x, y, null); } /// /// Draws another image into this one, at the given position and with scaling /// /// The target bitmap /// The source bitmap /// Rectangle in source image from where to draw /// Rectangle in target image where to draw to public static void DrawImage(this IGraphics graphics, BitmapImage source, Rectangle sourceRectangle, Rectangle targetRectangle) { var sourceBmp = (SkiaSharpBitmap)source; var targetCanvas = GetCanvas(graphics); targetCanvas.DrawBitmap(sourceBmp.WrappedBitmap, new SKRect(sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Right, sourceRectangle.Bottom), new SKRect(targetRectangle.Left, targetRectangle.Top, targetRectangle.Right, targetRectangle.Bottom)); } /// /// Get the internal SKCanvas instance, to manually draw to the target bitmap. /// /// The reference to the image /// An instance that can be used in calls for drawing methods public static SKCanvas GetCanvas(this IGraphics graphics) { if (graphics == null) { throw new ArgumentNullException(nameof(graphics)); } if (graphics is SkiaSharpBitmap.BitmapCanvas bitmapCanvas) { return bitmapCanvas.Canvas; } throw new ArgumentException("These extension methods can only be used on SkiaSharpBitmap instances", nameof(graphics)); } } }