protected static Bitmap GetBitmap(ImageClipStream ics, int width = 0) { TryReset(ics.Stream); using var ms = new MemoryStream(); ics.Stream.CopyTo(ms); TryReset(ms); using var bitmapSource = SKBitmap.Decode(ms); using var bitmapDest = new SKBitmap(bitmapSource.Width, bitmapSource.Height, SKColorType.Bgra8888, SKAlphaType.Unpremul); using var canvas = new SKCanvas(bitmapDest); var rect = ics.Circle ? new SKRect(0, 0, bitmapSource.Width, bitmapSource.Height) : new SKRect(ics.Left, ics.Top, ics.Right, ics.Bottom); var roundRect = ics.Circle ? new SKRoundRect(rect, bitmapSource.Width / 2f, bitmapSource.Height / 2f) : new SKRoundRect(rect, ics.Radius_X, ics.Radius_Y); canvas.ClipRoundRect(roundRect, antialias: true); canvas.DrawBitmap(bitmapSource, 0, 0); var stream = bitmapDest.Encode(SKEncodedImageFormat.Png, 100).AsStream(); TryReset(stream); //var tempFilePath = Path.Combine(IOPath.CacheDirectory, Path.GetFileName(Path.GetTempFileName() + ".png")); //using (var fs = File.Create(tempFilePath)) //{ // stream.CopyTo(fs); // TryReset(stream); //} return(GetDecodeBitmap(stream, width)); }
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); float dxShadow = SizeStroker / 2; if (ShowOut) { makeShadow(info, canvas, TypeShadow.down, dxShadow, dxShadow, Color.Black, BaseColor); makeShadow(info, canvas, TypeShadow.top, -dxShadow, -dxShadow, Color.White, BaseColor); } if (ShowInner) { var mask = makeBox(info, canvas, TypeShadow.top, -dxShadow, -dxShadow, Color.White, BaseColor); canvas.ClipRoundRect(mask, SKClipOperation.Intersect); makeInnerShadow(info, canvas, TypeShadow.down, -dxShadow, -dxShadow, Color.White, BaseColor); makeInnerShadow(info, canvas, TypeShadow.top, dxShadow, dxShadow, Color.Black, BaseColor); } }
private void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); float size = 600; float posX = (info.Width - size) / 2; float posY = (info.Height - size) / 2; using (SKPath path = new SKPath()) { var fillRect = SKRect.Create(info.Width, info.Height); var codeRect = SKRect.Create(posX, posY, size, size); var roundRect = new SKRoundRect(codeRect, 20); canvas.ClipRoundRect(roundRect, SKClipOperation.Difference, true); SKColor maskColor; SKColor.TryParse("003AB6", out maskColor); using (SKPaint paint = new SKPaint()) { paint.Style = SKPaintStyle.Fill; paint.Color = maskColor; canvas.DrawRect(fillRect, paint); } } }
public static SKBitmap ClipRoundRect(this SKBitmap bitmap, int cornerRadius) { var rect = new SKRoundRect(new SKRect(0, 0, bitmap.Width, bitmap.Height), cornerRadius); var skCanvas = new SKCanvas(bitmap); skCanvas.ClipRoundRect(rect); skCanvas.Flush(); skCanvas.Save(); return(bitmap); }
/// <summary> /// Clips the current drawing session. /// </summary> /// <param name="bounds">The bounds.</param> /// <param name="cornerRadius">The corner radius.</param> public void ClipRect(Rect bounds, CornerRadius cornerRadius) { if (cornerRadius.TopLeft > 0) { _canvas.ClipRoundRect(new SKRoundRect(bounds.ToSKRect(), cornerRadius.TopLeft.ToFloat(), cornerRadius.TopLeft.ToFloat()), SKClipOperation.Intersect, false); } else { _canvas.ClipRect(bounds.ToSKRect(), SKClipOperation.Intersect, false); } }
public void DrawHole(SKCanvas canvas, SKRect rect, float scale = 1) { if (Roundness <= 0) { canvas.ClipRect(new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom), SKClipOperation.Difference); } else { canvas.ClipRoundRect( new SKRoundRect(new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom), Roundness, Roundness), SKClipOperation.Difference); } }
private void PaintChessPattern(SKCanvas canvas, SliderLocation slider, SKSize canvasSize) { var pickerRadiusPixels = GetPickerRadiusPixels(); var sliderTop = slider.GetSliderOffset(pickerRadiusPixels); var scale = pickerRadiusPixels / 3; SKPath path = new SKPath(); path.MoveTo(-1 * scale, -1 * scale); path.LineTo(0 * scale, -1 * scale); path.LineTo(0 * scale, 0 * scale); path.LineTo(1 * scale, 0 * scale); path.LineTo(1 * scale, 1 * scale); path.LineTo(0 * scale, 1 * scale); path.LineTo(0 * scale, 0 * scale); path.LineTo(-1 * scale, 0 * scale); path.LineTo(-1 * scale, -1 * scale); SKMatrix matrix = SKMatrix.MakeScale(2 * scale, 2 * scale); SKPaint paint = new SKPaint { PathEffect = SKPathEffect.Create2DPath(matrix, path), Color = Color.LightGray.ToSKColor(), IsAntialias = true }; SKRect patternRect; SKRect clipRect; SKRoundRect clipRoundRect; if (Vertical) { patternRect = new SKRect(sliderTop - pickerRadiusPixels, pickerRadiusPixels , sliderTop + pickerRadiusPixels, canvasSize.Height - pickerRadiusPixels); clipRect = new SKRect(sliderTop - (pickerRadiusPixels * 0.65f), pickerRadiusPixels * 1.35f , sliderTop + (pickerRadiusPixels * 0.65f), canvasSize.Height - (pickerRadiusPixels * 1.35f)); clipRoundRect = new SKRoundRect(clipRect, pickerRadiusPixels * 0.65f, pickerRadiusPixels * 0.65f); } else { patternRect = new SKRect(pickerRadiusPixels, sliderTop - pickerRadiusPixels , canvasSize.Width - pickerRadiusPixels, sliderTop + pickerRadiusPixels); clipRect = new SKRect(pickerRadiusPixels * 1.35f, sliderTop - (pickerRadiusPixels * 0.65f) , canvasSize.Width - (pickerRadiusPixels * 1.35f), sliderTop + (pickerRadiusPixels * 0.65f)); clipRoundRect = new SKRoundRect(clipRect, pickerRadiusPixels * 0.65f, pickerRadiusPixels * 0.65f); } canvas.Save(); canvas.ClipRoundRect(clipRoundRect); canvas.DrawRect(patternRect, paint); canvas.Restore(); }
protected override void DrawInternal(SKCanvas canvas) { const float radius = 10; canvas.DrawRoundRect(BoundsLocal, radius, radius, Paint); if (Background != null) { using (new SKAutoCanvasRestore(canvas)) { canvas.ClipRoundRect(new SKRoundRect(BoundsLocal, radius), antialias: true); DrawBackgroundInternal(canvas); } } Content.Draw(canvas); }
private SKBitmap DrawBitmapIcon(byte[] imageData, bool isSvg, SKSizeI pictureSize, SKSizeI backgroundSize, SKColor?imageMaskColor = null, SKColor?backgroundColor = null, float?cornerRadius = null) { var bitmap = GetSKBitmap(imageData, isSvg, pictureSize); if (imageMaskColor != null) { bitmap = bitmap.ApplyMask(imageMaskColor.Value); } var result = new SKBitmap( backgroundSize.Width, backgroundSize.Height); var skCanvas = new SKCanvas(result); var xRadius = cornerRadius == null ? 0 : backgroundSize.Width / 2.0f * cornerRadius.Value; var yRadius = cornerRadius == null ? 0 : backgroundSize.Height / 2.0f * cornerRadius.Value; var rect = new SKRoundRect( new SKRect(0, 0, backgroundSize.Width, backgroundSize.Height), xRadius, yRadius); skCanvas.ClipRoundRect(rect, SKClipOperation.Intersect, true); skCanvas.Clear(backgroundColor ?? SKColors.Transparent); skCanvas.DrawBitmap(bitmap, (backgroundSize.Width - pictureSize.Width) / 2.0f, (backgroundSize.Height - pictureSize.Height) / 2.0f); skCanvas.Flush(); skCanvas.Save(); var skData = SKImage.FromBitmap(result).Encode( SKEncodedImageFormat.Png, 100); var data = skData.ToArray(); return(SKBitmap.Decode(data)); }
/// <inheritdoc /> public void DrawRectangle(IBrush brush, IPen pen, RoundedRect rect, BoxShadows boxShadows = default) { if (rect.Rect.Height <= 0 || rect.Rect.Width <= 0) { return; } // Arbitrary chosen values // On OSX Skia breaks OpenGL context when asked to draw, e. g. (0, 0, 623, 6666600) rect if (rect.Rect.Height > 8192 || rect.Rect.Width > 8192) { boxShadows = default; } var rc = rect.Rect.ToSKRect(); var isRounded = rect.IsRounded; var needRoundRect = rect.IsRounded || (boxShadows.HasInsetShadows); using var skRoundRect = needRoundRect ? new SKRoundRect() : null; if (needRoundRect) { skRoundRect.SetRectRadii(rc, new[] { rect.RadiiTopLeft.ToSKPoint(), rect.RadiiTopRight.ToSKPoint(), rect.RadiiBottomRight.ToSKPoint(), rect.RadiiBottomLeft.ToSKPoint(), }); } foreach (var boxShadow in boxShadows) { if (!boxShadow.IsEmpty && !boxShadow.IsInset) { using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, _currentOpacity)) { var spread = (float)boxShadow.Spread; if (boxShadow.IsInset) { spread = -spread; } Canvas.Save(); if (isRounded) { using var shadowRect = new SKRoundRect(skRoundRect); if (spread != 0) { shadowRect.Inflate(spread, spread); } Canvas.ClipRoundRect(skRoundRect, shadow.ClipOperation, true); var oldTransform = Transform; Transform = oldTransform * Matrix.CreateTranslation(boxShadow.OffsetX, boxShadow.OffsetY); Canvas.DrawRoundRect(shadowRect, shadow.Paint); Transform = oldTransform; } else { var shadowRect = rc; if (spread != 0) { shadowRect.Inflate(spread, spread); } Canvas.ClipRect(rc, shadow.ClipOperation); var oldTransform = Transform; Transform = oldTransform * Matrix.CreateTranslation(boxShadow.OffsetX, boxShadow.OffsetY); Canvas.DrawRect(shadowRect, shadow.Paint); Transform = oldTransform; } Canvas.Restore(); } } } if (brush != null) { using (var paint = CreatePaint(_fillPaint, brush, rect.Rect.Size)) { if (isRounded) { Canvas.DrawRoundRect(skRoundRect, paint.Paint); } else { Canvas.DrawRect(rc, paint.Paint); } } } foreach (var boxShadow in boxShadows) { if (!boxShadow.IsEmpty && boxShadow.IsInset) { using (var shadow = BoxShadowFilter.Create(_boxShadowPaint, boxShadow, _currentOpacity)) { var spread = (float)boxShadow.Spread; var offsetX = (float)boxShadow.OffsetX; var offsetY = (float)boxShadow.OffsetY; var outerRect = AreaCastingShadowInHole(rc, (float)boxShadow.Blur, spread, offsetX, offsetY); Canvas.Save(); using var shadowRect = new SKRoundRect(skRoundRect); if (spread != 0) { shadowRect.Deflate(spread, spread); } Canvas.ClipRoundRect(skRoundRect, shadow.ClipOperation, true); var oldTransform = Transform; Transform = oldTransform * Matrix.CreateTranslation(boxShadow.OffsetX, boxShadow.OffsetY); using (var outerRRect = new SKRoundRect(outerRect)) Canvas.DrawRoundRectDifference(outerRRect, shadowRect, shadow.Paint); Transform = oldTransform; Canvas.Restore(); } } } if (pen?.Brush != null) { using (var paint = CreatePaint(_strokePaint, pen, rect.Rect.Size)) { if (isRounded) { Canvas.DrawRoundRect(skRoundRect, paint.Paint); } else { Canvas.DrawRect(rc, paint.Paint); } } } }
private void SkiaOverlay_PaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs e) { SKImageInfo info = e.Info; SKSurface surface = e.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); float paddingPx = (float)padding * (float)_density; float left = paddingPx; float top = (float)(anim[AnimationKey.Cell].Current * _density) + paddingPx; float right = info.Width - paddingPx; float bottom = top + (float)(cellHeight * _density) - paddingPx; // adjust the cutout based on the expand animation float expandValue = (float)(anim[AnimationKey.Expand].Current * _density); if (expandValue > 0) { // change the values left -= expandValue; if (left < 0) { left = 0; } right += expandValue; if (right > info.Width) { right = info.Width; } top -= expandValue; if (top < 0) { top = 0; } bottom += expandValue; if (bottom > info.Height) { bottom = info.Height; } } // create a cutout var cornerRadius = (paddingPx * 2) - expandValue; // store the state of the canvas using (new SKAutoCanvasRestore(canvas)) { var cutoutRect = new SKRect(left, top, right, bottom); canvas.ClipRoundRect(new SKRoundRect(cutoutRect, cornerRadius, cornerRadius), SKClipOperation.Difference, true); // draw the background SKRect backgroundRect = new SKRect(0, 0, info.Width, info.Height); canvas.DrawBitmap(mapbackground, backgroundRect, BitmapStretch.AspectFill); } // draw the flyup - but only when it should be float flyupPos = (float)(anim[AnimationKey.FlyUp].Current * _density); float circleRadius = (float)(anim[AnimationKey.Circle].Current * _density); if (flyupPos < info.Height) { SKPoint circleCenter = new SKPoint(info.Width / 2, flyupPos); // draw the center circle canvas.DrawCircle(circleCenter, circleRadius - (float)(10 * _density), centerCirclePaint); // add the aircraft image float aircraftScale = .6f; float aircraftSize = (circleRadius * 2f) * aircraftScale; SKRect aircraftRect = new SKRect(0, 0, aircraftSize, aircraftSize); aircraftRect.Location = new SKPoint((info.Width / 2) - (aircraftSize / 2), flyupPos - (aircraftSize / 2)); canvas.DrawBitmap(aircraftImage, aircraftRect, BitmapStretch.AspectFit); // create a circle clip SKPath circlePath = new SKPath(); circlePath.AddCircle(info.Width / 2, flyupPos, circleRadius); canvas.ClipPath(circlePath, SKClipOperation.Difference, true); SKRect flyupRect = new SKRect(0, flyupPos, info.Width, info.Height); canvas.DrawRect(flyupRect, flyupPaint); } }
private async Task <byte[]> GenerateDiagram(CommandContext ctx, IEnumerable <IGrouping <long, Slavereports> > groupedReports, TimeSpan timespan) { if (groupedReports.Count() > 5) { throw new ArgumentOutOfRangeException("Maximum allowed number of users in a diagram is 5"); } const int ImageWidth = 1024; const int ImageHeight = 800; const int DiagramSpacingLeft = 90; // Spacing on the left of the Y line const int DiagramSpacingBottom = 120; // Spacing below the X line SKBitmap bmp = new SKBitmap(ImageWidth, ImageHeight); using SKCanvas canvas = new SKCanvas(bmp); // Set black background canvas.Clear(new SKColor(47, 49, 54)); // Create all colors and strokes needed later on SKPaint diagramPaint = new SKPaint() { Color = new SKColor(200, 200, 230), StrokeWidth = 3, IsAntialias = true, }; SKPaint diagramPaintThicc = new SKPaint() { Color = new SKColor(200, 200, 230), StrokeWidth = 6, IsAntialias = true }; SKPaint textPaint = new SKPaint() { Color = new SKColor(200, 200, 230), TextSize = 18f, TextAlign = SKTextAlign.Center, IsAntialias = true, IsEmbeddedBitmapText = true }; SKPaint leftTextPaint = new SKPaint() { Color = new SKColor(200, 200, 230), TextSize = 18f, TextAlign = SKTextAlign.Right, IsAntialias = true, IsEmbeddedBitmapText = true }; // Draw X and Y lines canvas.DrawLine(new SKPoint(DiagramSpacingLeft, 0), new SKPoint(DiagramSpacingLeft, ImageHeight), diagramPaint); canvas.DrawLine(new SKPoint(0, ImageHeight - DiagramSpacingBottom), new SKPoint(ImageWidth, ImageHeight - DiagramSpacingBottom), diagramPaint); const int rows = 8; // max and min time of all reports var maxTime = groupedReports.Max(g => g.Max(r => r.TimeSpan)); var minTime = groupedReports.Min(g => g.Min(r => r.TimeSpan)); var timeDiff = TimeSpan.FromTicks(maxTime - minTime); var individualTime = TimeSpan.FromTicks(maxTime / rows); var individualRowSpacing = Convert.ToInt32((ImageHeight - DiagramSpacingBottom * 1.4f) / rows); var individualColumnSpacing = Convert.ToInt32((ImageWidth - DiagramSpacingLeft * 1.4f) / (timespan.TotalDays + 1)); for (int i = 1; i <= rows; i++) { var y = ImageHeight - DiagramSpacingBottom - individualRowSpacing * i; canvas.DrawLine(new SKPoint(DiagramSpacingLeft - 10, y), new SKPoint(DiagramSpacingLeft + 10, y), diagramPaintThicc); canvas.DrawText((individualTime * i).ToString("hh\\:mm\\:ss"), new SKPoint(DiagramSpacingLeft - 10, y - 10), leftTextPaint); } var xLineHeight = ImageHeight - DiagramSpacingBottom; for (int i = 1; i <= timespan.TotalDays + 2; i++) { var x = DiagramSpacingLeft + individualColumnSpacing * i; canvas.DrawLine(new SKPoint(x, xLineHeight - 10), new SKPoint(x, xLineHeight + 10), diagramPaintThicc); canvas.DrawText((DateTime.Now - timespan + TimeSpan.FromDays(1) + TimeSpan.FromDays(i - 1)).ToString("dd.MM."), new SKPoint(x, xLineHeight + 30), textPaint); } // Create a color for each user SKColor[] userColors = new SKColor[] { new SKColor(36, 123, 160), new SKColor(112, 193, 179), new SKColor(178, 219, 191), new SKColor(243, 255, 189), new SKColor(225, 22, 84) }; for (int i = 0; i < groupedReports.Count(); i++) { var group = groupedReports.ElementAt(i); var color = userColors[i]; var colorBright = new SKColor((byte)(color.Red + 100 > 255 ? 255 : color.Red + 100), (byte)(color.Green + 100 > 255 ? 255 : color.Green + 100), (byte)(color.Blue + 100 > 255 ? 255 : color.Blue + 100)); var paint = new SKPaint() { Color = color, StrokeWidth = 3, TextSize = 18f, TextAlign = SKTextAlign.Center, IsAntialias = true, IsEmbeddedBitmapText = true }; var paintBright = new SKPaint() { Color = colorBright, StrokeWidth = 3, TextSize = 18f, TextAlign = SKTextAlign.Center, IsAntialias = true, IsEmbeddedBitmapText = true }; SKPoint lastCoord = SKPoint.Empty; var user = await ctx.Client.GetUserAsync(Convert.ToUInt64(group.Key)); var spacePerUser = (ImageWidth - DiagramSpacingLeft) / 5; // Get the avatar HttpClient httpClient = new HttpClient(); var userImgResponse = await httpClient.GetAsync(user.AvatarUrl); // Only add the user avatar if it can be downloaded if (userImgResponse.IsSuccessStatusCode) { DiscordMember member = null; try { member = await ctx.Channel.Guild.GetMemberAsync(user.Id); } catch (Exception) { } var antialiasedPaint = new SKPaint() { IsAntialias = true }; textPaint.GetFontMetrics(out SKFontMetrics metrics); var textSpacing = Convert.ToInt32(metrics.XMax + (metrics.XMax / 4)); var x = DiagramSpacingLeft + 5 + spacePerUser * i; var y = ImageHeight - DiagramSpacingBottom + textSpacing; var fullSpace = DiagramSpacingBottom - textSpacing < spacePerUser ? DiagramSpacingBottom : spacePerUser; var halfSpace = fullSpace / 2; var left = halfSpace / 4 * 1; var top = halfSpace / 4 * 1; var size = halfSpace / 4 * 3; var baseBmp = new SKBitmap(spacePerUser, fullSpace - Convert.ToInt32(textSpacing)); var baseCanvas = new SKCanvas(baseBmp); baseCanvas.Clear(color); var userImgBmp = SKBitmap.Decode(await userImgResponse.Content.ReadAsStreamAsync()); var clippedBmp = new SKBitmap(userImgBmp.Width, userImgBmp.Height); SKCanvas userImgCanvas = new SKCanvas(clippedBmp); userImgCanvas.ClipRoundRect(new SKRoundRect(new SKRect(0, 0, userImgBmp.Width, userImgBmp.Height), 100, 100)); userImgCanvas.DrawBitmap(userImgBmp, 0, 0, antialiasedPaint); userImgCanvas.Flush(); baseCanvas.DrawBitmap(clippedBmp, new SKRect(left, top, left + size, top + size), antialiasedPaint); SKPaint namePaint = new SKPaint() { Color = new SKColor(47, 49, 54), TextAlign = SKTextAlign.Left, TextSize = 18, IsAntialias = true, IsEmbeddedBitmapText = true, }; DrawTextArea(baseCanvas, namePaint, left * 2 + size, top * 2, spacePerUser - left * 2 + size, 15, member?.Nickname ?? user.Username); canvas.DrawBitmap(baseBmp, new SKPoint(x, y), antialiasedPaint); } foreach (var report in group) { var minDate = (DateTime.Now - timespan).Date; var maxDate = (DateTime.Now + TimeSpan.FromDays(1)).Date; var totalSpace = individualColumnSpacing * (timespan.TotalDays + 1); var percentPointPerTick = (float)totalSpace / (maxDate - minDate).Ticks; var x = DiagramSpacingLeft + (percentPointPerTick * (report.TimeOfReport - minDate).Ticks); //Subtract the time of the report from the mindate, to get the time relative from the beginning of the graph. multiply by percentagepoint of a tick on the graph. add spacing, var y = ImageHeight - DiagramSpacingBottom - ((ImageHeight - (DiagramSpacingBottom * 1.4f)) / Convert.ToSingle(maxTime) * report.TimeSpan); var coord = new SKPoint(x, y); canvas.DrawCircle(coord, 8, paint); canvas.DrawText(TimeSpan.FromTicks(report.TimeSpan).ToString(), new SKPoint(coord.X, coord.Y - 10), paintBright); //canvas.DrawText(report.TimeOfReport.ToString(), new SKPoint(coord.X, coord.Y + 15), paintBright); if (lastCoord != SKPoint.Empty) { canvas.DrawLine(lastCoord, coord, paint); } lastCoord = coord; } } using var ms = new MemoryStream(); using SKManagedWStream skStream = new SKManagedWStream(ms); if (SKPixmap.Encode(skStream, bmp, SKEncodedImageFormat.Png, 100)) { return(ms.ToArray()); } return(Array.Empty <byte>()); }