private void Paint(SKCanvasView canvasView) { using (var recorder = new SKPictureRecorder()) using (var canvas = recorder.BeginRecording(SKRect.Create(SKPoint.Empty, Size))) { try { Page.Render(canvas, Size); } catch (Exception ex) { using (var paint = new SKPaint { Color = SKColors.DarkRed }) { canvas.Save(); if (canvas.TotalMatrix.ScaleY < 0) { var matrix = SKMatrix.MakeScale(1, -1); canvas.Concat(ref matrix); } canvas.DrawText(ex.Message, 0, 0, paint); canvas.Restore(); } } picture = recorder.EndRecording(); } //text var positionComparator = new TextStringPositionComparer <ITextString>(); Page.Strings.Sort(positionComparator); Xamarin.Forms.Device.BeginInvokeOnMainThread(() => canvasView.InvalidateSurface()); }
public SKPicture?RecordGraphic(Drawable?drawable, Attributes ignoreAttributes) { // TODO: Record using SKColorSpace.CreateSrgbLinear because .color-interpolation-filters. is by default linearRGB. if (drawable == null) { return(null); } if (drawable.TransformedBounds.Width <= 0f && drawable.TransformedBounds.Height <= 0f) { return(null); } using var skPictureRecorder = new SKPictureRecorder(); using var skCanvas = skPictureRecorder.BeginRecording(drawable.TransformedBounds); #if USE_EXPERIMENTAL_LINEAR_RGB // TODO: using var skPaint = new SKPaint(); using var skColorFilter = SKColorFilter.CreateTable(null, SvgPaintingExtensions.s_SRGBtoLinearRGB, SvgPaintingExtensions.s_SRGBtoLinearRGB, SvgPaintingExtensions.s_SRGBtoLinearRGB); using var skImageFilter = SKImageFilter.CreateColorFilter(skColorFilter); skPaint.ImageFilter = skImageFilter; skCanvas.SaveLayer(skPaint); #endif drawable.Draw(skCanvas, ignoreAttributes, null); #if USE_EXPERIMENTAL_LINEAR_RGB // TODO: skCanvas.Restore(); #endif return(skPictureRecorder.EndRecording()); }
public static SKPicture?ToPicture(SvgFragment svgFragment) { var skSize = SvgExtensions.GetDimensions(svgFragment); var skBounds = SKRect.Create(skSize); using var drawable = DrawableFactory.Create(svgFragment, skBounds, null, null, Attributes.None); if (drawable == null) { return(null); } drawable.PostProcess(); if (skBounds.IsEmpty) { skBounds = GetBounds(drawable); } using var skPictureRecorder = new SKPictureRecorder(); using var skCanvas = skPictureRecorder.BeginRecording(skBounds); #if USE_EXPERIMENTAL_LINEAR_RGB // TODO: using var skPaint = new SKPaint(); using var skColorFilter = SKColorFilter.CreateTable(null, SvgPaintingExtensions.s_LinearRGBtoSRGB, SvgPaintingExtensions.s_LinearRGBtoSRGB, SvgPaintingExtensions.s_LinearRGBtoSRGB); using var skImageFilter = SKImageFilter.CreateColorFilter(skColorFilter); skPaint.ImageFilter = skImageFilter; skCanvas.SaveLayer(skPaint); #endif drawable?.Draw(skCanvas, 0f, 0f); #if USE_EXPERIMENTAL_LINEAR_RGB // TODO: skCanvas.Restore(); #endif return(skPictureRecorder.EndRecording()); }
internal static void ExportSkp(IToolContext context, string path, IContainerView containerView) { var recorder = new SKPictureRecorder(); var rect = new SKRect(0f, 0f, (float)containerView.Width, (float)containerView.Height); var canvas = recorder.BeginRecording(rect); using (var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView)) { skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0); } var picture = recorder.EndRecording(); var dimensions = new SKSizeI((int)containerView.Width, (int)containerView.Height); using (var image = SKImage.FromPicture(picture, dimensions)) { var data = image.EncodedData; if (data != null) { using (var stream = File.OpenWrite(path)) { data.SaveTo(stream); } } } picture.Dispose(); }
private SKPicture Load(XDocument xdoc) { var svg = xdoc.Root; var ns = svg.Name.Namespace; // find the defs (gradients) - and follow all hrefs foreach (var d in svg.Descendants()) { var id = d.Attribute("id")?.Value?.Trim(); if (!string.IsNullOrEmpty(id)) { defs[id] = ReadDefinition(d); } } Version = svg.Attribute("version")?.Value; Title = svg.Element(ns + "title")?.Value; Description = svg.Element(ns + "desc")?.Value ?? svg.Element(ns + "description")?.Value; if (CanvasSize.IsEmpty) { // get the dimensions var widthA = svg.Attribute("width"); var heightA = svg.Attribute("height"); var width = ReadNumber(widthA); var height = ReadNumber(heightA); var size = new SKSize(width, height); var viewBox = SKRect.Create(size); var viewBoxA = svg.Attribute("viewBox") ?? svg.Attribute("viewPort"); if (viewBoxA != null) { viewBox = ReadRectangle(viewBoxA.Value); } if (widthA != null && widthA.Value.Contains("%")) { size.Width *= viewBox.Width; } if (heightA != null && heightA.Value.Contains("%")) { size.Height *= viewBox.Height; } // set the property CanvasSize = size; } // create the picture from the elements using (var recorder = new SKPictureRecorder()) using (var canvas = recorder.BeginRecording(SKRect.Create(CanvasSize))) { LoadElements(svg.Elements(), canvas); Picture = recorder.EndRecording(); } return(Picture); }
public void Save(Stream stream, PageContainerViewModel container) { using var pictureRecorder = new SKPictureRecorder(); using var canvas = pictureRecorder.BeginRecording(SKRect.Create(0, 0, (int)container.Template.Width, (int)container.Template.Height)); _presenter.Render(canvas, _renderer, null, container, 0, 0); using var picture = pictureRecorder.EndRecording(); picture.Serialize(stream); }
public SKPicture Snapshot(SKRect bounds) { var skPictureRecorder = new SKPictureRecorder(); var skCanvas = skPictureRecorder.BeginRecording(bounds); OnDraw(skCanvas); return(skPictureRecorder.EndRecording()); }
private SKPicture RecordPicture(IContainerView view, IShapeRenderer renderer, double scale, Action <IContainerView, SKCanvas, IShapeRenderer, double> draw) { var recorder = new SKPictureRecorder(); var rect = new SKRect(0f, 0f, (float)view.Width, (float)view.Height); var canvas = recorder.BeginRecording(rect); draw(view, canvas, renderer, scale); return(recorder.EndRecording()); }
public static void RenderCallout(CalloutStyle callout) { if (callout.Content < 0) { return; } // Get size of content double contentWidth = 0; double contentHeight = 0; if (callout.Type == CalloutType.Custom) { var bitmapInfo = BitmapHelper.LoadBitmap(BitmapRegistry.Instance.Get(callout.Content)); contentWidth = bitmapInfo?.Width ?? 0; contentHeight = bitmapInfo?.Height ?? 0; } else if (callout.Type == CalloutType.Single || callout.Type == CalloutType.Detail) { var picture = (SKPicture)BitmapRegistry.Instance.Get(callout.Content); contentWidth = picture.CullRect.Width; contentHeight = picture.CullRect.Height; } (var width, var height) = CalcSize(callout, contentWidth, contentHeight); // Create a canvas for drawing using (var rec = new SKPictureRecorder()) using (var canvas = rec.BeginRecording(new SKRect(0, 0, (float)width, (float)height))) { (var path, var center) = CreateCalloutPath(callout, contentWidth, contentHeight); // Now move Offset to the position of the arrow callout.Offset = new Offset(-center.X, -center.Y); // Draw path for bubble DrawCallout(callout, canvas, path); // Draw content DrawContent(callout, canvas); // Create SKPicture from canvas var picture = rec.EndRecording(); if (callout.BitmapId < 0) { callout.BitmapId = BitmapRegistry.Instance.Register(picture); } else { BitmapRegistry.Instance.Set(callout.BitmapId, picture); } } callout.Invalidated = false; }
protected static SKPicture CreateTestPicture(byte alpha = 255) { using var recorder = new SKPictureRecorder(); using var canvas = recorder.BeginRecording(SKRect.Create(0, 0, 40, 40)); DrawTestBitmap(canvas, 40, 40, alpha); return(recorder.EndRecording()); }
private void SkCanvas_OnPaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { SKImageInfo info = new SKImageInfo(e.BackendRenderTarget.Width, e.BackendRenderTarget.Height, e.ColorType); SKSurface surface = e.Surface; SKCanvas surfaceCanvas = surface.Canvas; surfaceCanvas.Clear(); surfaceCanvas.SetMatrix(_canvasMatrix); if (_picture == null) { using (SKPictureRecorder pictureRecorder = new SKPictureRecorder()) using (SKCanvas canvas = pictureRecorder.BeginRecording(info.Rect)) using (SKPath path = new SKPath()) { /* * Draw path with multiple segments(>=3). * Then every time you translate the surfaceCanvas, it consumes more GPU memory. */ path.CubicTo(150, 50, 200, 125, 300, 25); // path.LineTo(80, 125); // path.LineTo(130, 75); // path.LineTo(200, 205); canvas.DrawPath(path, _paint); // Fine with DrawRoundRect or DrawText // canvas.DrawText("TEXT", new SKPoint(50, 50), _paint); // canvas.DrawRoundRect(120,120,300,220,12,12,paint); _picture = pictureRecorder.EndRecording(); } } surfaceCanvas.DrawPicture(_picture); /* * Directly drawing on surfaceCanvas is fine. */ // using (SKPath path = new SKPath()) // { // path.CubicTo(150, 50, 200, 125, 300, 25); // // path.LineTo(80, 125); // path.LineTo(130, 75); // path.LineTo(200, 205); // // surfaceCanvas.DrawPath(path, _paint); // } }
/// <summary> /// Create image tile from all sources that are contained in the MGLStyleFile /// </summary> /// <param name="styleFile">StyleFile to use</param> /// <param name="tile">TileInfo of tile to draw</param> /// <param name="tileSize">Tile size of the image tile</param> /// <returns>Byte array of image data</returns> private static byte[] CreateTile(MGLStyleFile styleFile, TileInfo tile, int tileSize) { var recorder = new SKPictureRecorder(); var stopwatch = new System.Diagnostics.Stopwatch(); recorder.BeginRecording(new SKRect(0, 0, tileSize, tileSize)); var canvas = recorder.RecordingCanvas; canvas.ClipRect(new SKRect(0, 0, tileSize, tileSize)); if (styleFile.TileSources != null && styleFile.TileSources.Count > 0) { // We have one or more sources, so draw each source after the other foreach (var source in styleFile.TileSources) { stopwatch.Start(); var vectorDrawable = source.GetDrawable(tile); stopwatch.Stop(); stopwatchResults.Add($"Ellapsed time for GetDrawable of ${source.Name}: {stopwatch.ElapsedMilliseconds} ms"); stopwatch.Reset(); stopwatch.Start(); if (vectorDrawable is SKDrawable drawable) { vectorDrawable.Context.Zoom = float.Parse(tile.Index.Level); vectorDrawable.Context.Tags = null; canvas.Save(); canvas.Scale(tileSize / drawable.Bounds.Width); canvas.DrawDrawable(drawable, 0, 0); canvas.Restore(); } stopwatch.Stop(); stopwatchResults.Add($"Ellapsed time for DrawDrawable of ${source.Name}: {stopwatch.ElapsedMilliseconds} ms"); stopwatch.Reset(); } } stopwatch.Start(); var byteArray = SKImage.FromPicture(recorder.EndRecording(), new SKSizeI(tileSize, tileSize), new SKPaint() { IsAntialias = true }).Encode().ToArray(); stopwatch.Stop(); stopwatchResults.Add($"Ellapsed time for drawing picture: {stopwatch.ElapsedMilliseconds} ms"); return(byteArray); }
public void Setup(SKCanvas canvas, double scale) { if (!Enabled) { return; } strokes.Clear(); // try to get roughly 15 vertical lines in portrait, rounding to the nearest 10 pixel // if (Config.GridSize < 0) { var theLength = Math.Min(canvas.ClipBounds.Width, canvas.ClipBounds.Height); Config.GridSize = ((((int)theLength / 15) + 5) / 10) * 10; } var baseStroke = new Stroke { Size = LineWidth * scale, ToolSettings = new ToolSettings { SelectedColor = LineColor } }; int counter = 0; do { var stroke = new Stroke(baseStroke); stroke.Points.Add(new Point { X = counter * Config.GridSize, Y = 0 }); stroke.Points.Add(new Point { X = counter * Config.GridSize, Y = canvas.ClipBounds.Height }); strokes.Add(stroke); counter++; } while ((counter * Config.GridSize) < canvas.ClipBounds.Width); counter = 0; do { var stroke = new Stroke(baseStroke); stroke.Points.Add(new Point { X = 0, Y = counter * Config.GridSize }); stroke.Points.Add(new Point { X = canvas.ClipBounds.Width, Y = counter * Config.GridSize }); strokes.Add(stroke); counter++; } while (counter * Config.GridSize < canvas.ClipBounds.Height); // Drawing the grid to a picture. // A tad faster than drawing directly on the canvas. No big impact though using (var recorder = new SKPictureRecorder()) { recorder.BeginRecording(canvas.ClipBounds); DrawBackbuffer(recorder.RecordingCanvas); _gridPicture = recorder.EndRecording(); } }
public static void Render(Control target, Size size, Stream stream, double dpi = 96, bool useDeferredRenderer = false) { var bounds = SKRect.Create(new SKSize((float)size.Width, (float)size.Height)); using var pictureRecorder = new SKPictureRecorder(); using var canvas = pictureRecorder.BeginRecording(bounds); target.Measure(size); target.Arrange(new Rect(size)); CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer); using var picture = pictureRecorder.EndRecording(); picture.Serialize(stream); }
public void CanSerializeAndDeserializePicture() { using var recorder = new SKPictureRecorder(); using var canvas = recorder.BeginRecording(SKRect.Create(0, 0, 40, 40)); using var picture = recorder.EndRecording(); using var data = picture.Serialize(); using var deserialized = SKPicture.Deserialize(data); Assert.NotNull(deserialized); }
internal SKPicture Load(SvgFragment svgFragment) { var skSize = SkiaUtil.GetDimensions(svgFragment); var cullRect = SKRect.Create(skSize); using (var skPictureRecorder = new SKPictureRecorder()) using (var skCanvas = skPictureRecorder.BeginRecording(cullRect)) using (var renderer = new SKSvgRenderer(skCanvas, skSize)) { renderer.DrawFragment(svgFragment, false); return(skPictureRecorder.EndRecording()); } }
public SKPicture GetPicture() { if (picture != null) { return(picture); } var box = Box; using (var recorder = new SKPictureRecorder()) // SKBitmap((int)box.Width, (int)box.Height); using (var canvas = recorder.BeginRecording(SKRect.Create(box.Width, box.Height))) { Render(canvas, box.Size, false); return(picture = recorder.EndRecording()); } }
public SKPicture Flatten(SKRect bounds) { TRACE_EVENT0("flutter", "LayerTree::Flatten"); SKPictureRecorder recorder = new SKPictureRecorder(); var canvas = recorder.BeginRecording(bounds); if (canvas == null) { return(null); } Stopwatch unused_stopwatch = new Stopwatch(); TextureRegistry unused_texture_registry = new TextureRegistry(); SKMatrix root_surface_transformation = new SKMatrix(); // No root surface transformation. So assume identity. canvas.ResetMatrix(); PrerollContext preroll_context = new PrerollContext( null, null, null, SKRect.Empty, unused_stopwatch, unused_stopwatch, unused_texture_registry, false); Layer.PaintContext paint_context = new Layer.PaintContext( canvas, null, unused_stopwatch, unused_stopwatch, unused_texture_registry, null, false); // Even if we don't have a root layer, we still need to create an empty // picture. if (root_layer_ != null) { root_layer_.Preroll(preroll_context, root_surface_transformation); // The needs painting flag may be set after the preroll. So check it after. if (root_layer_.needs_painting()) { root_layer_.Paint(paint_context); } } return(recorder.EndRecording()); }
internal SKPicture Load(SvgFragment svgFragment) { using (var disposable = new CompositeDisposable()) { float width = svgFragment.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgFragment); float height = svgFragment.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgFragment); var skSize = new SKSize(width, height); var cullRect = SKRect.Create(skSize); using (var skPictureRecorder = new SKPictureRecorder()) using (var skCanvas = skPictureRecorder.BeginRecording(cullRect)) { SvgHelper.DrawSvgElement(skCanvas, skSize, svgFragment, disposable); return(skPictureRecorder.EndRecording()); } } }
protected override void OnRender(WpfDrawingContext drawingContext) { var source = PresentationSource.FromVisual(this); var dpix = (float)source.CompositionTarget.TransformToDevice.M11; var dpiy = (float)source.CompositionTarget.TransformToDevice.M22; var skPictureRecorder = new SKPictureRecorder(); // TODO: Can we restrict the culling rect here? SKRect skCullingRect = SKRect.Create(float.MinValue, float.MinValue, float.MaxValue, float.MaxValue); SKCanvas canvas = skPictureRecorder.BeginRecording(skCullingRect); DrawingContext context = new DrawingContext(canvas); context.Push(Matrix.Scale(dpix, dpiy)); RenderLayer(context); renderCache = skPictureRecorder.EndRecording(); if (context.IsVisible) { if (element != null) { element.InvalidateVisual(); } else { element = new(); element.PaintSurface += Element_PaintSurface; AddVisualChild(element); element.Measure(size); element.Arrange(new(size)); } } if (renderedChildren.Count > 0) { // In some cases children will be removed before measure is called again. // Don't update child order unless we're up to date. if (children.Count == renderedChildren.Count) { children = renderedChildren; } renderedChildren = new List <UIElement>(); } base.OnRender(drawingContext); }
public SKPicture?RecordBackground(Drawable?drawable, Attributes ignoreAttributes) { // TODO: Record using SKColorSpace.CreateSrgbLinear because 'color-interpolation-filters' is by default linearRGB. if (drawable == null) { return(null); } var container = FindContainerParentBackground(drawable, out var skClipRect); if (container != null) { using var skPictureRecorder = new SKPictureRecorder(); using var skCanvas = skPictureRecorder.BeginRecording(container.TransformedBounds); if (!skClipRect.IsEmpty) { skCanvas.ClipRect(skClipRect, SKClipOperation.Intersect); } #if USE_EXPERIMENTAL_LINEAR_RGB // TODO: using var skPaint = new SKPaint(); using var skColorFilter = SKColorFilter.CreateTable(null, SvgPaintingExtensions.s_SRGBtoLinearRGB, SvgPaintingExtensions.s_SRGBtoLinearRGB, SvgPaintingExtensions.s_SRGBtoLinearRGB); using var skImageFilter = SKImageFilter.CreateColorFilter(skColorFilter); skPaint.ImageFilter = skImageFilter; skCanvas.SaveLayer(skPaint); #endif container.Draw(skCanvas, ignoreAttributes, drawable); #if USE_EXPERIMENTAL_LINEAR_RGB // TODO: skCanvas.Restore(); #endif return(skPictureRecorder.EndRecording()); } return(null); }
public static SKPicture?ToPicture(SvgFragment svgFragment, out Drawable?drawable) { var skSize = SvgExtensions.GetDimensions(svgFragment); var skBounds = SKRect.Create(skSize); drawable = DrawableFactory.Create(svgFragment, skBounds, null, null, Attributes.None); if (drawable == null) { return(null); } drawable.PostProcess(); if (skBounds.IsEmpty) { skBounds = GetBounds(drawable); } using var skPictureRecorder = new SKPictureRecorder(); using var skCanvas = skPictureRecorder.BeginRecording(skBounds); drawable?.Draw(skCanvas, 0f, 0f); return(skPictureRecorder.EndRecording()); }
internal static SKPicture ToSKPicture(string path) { var extension = Path.GetExtension(path); if (string.Compare(extension, ".svg", StringComparison.OrdinalIgnoreCase) == 0) { var xml = File.ReadAllText(path); if (!string.IsNullOrEmpty(xml)) { return(SvgToSKPicture(xml)); } return(null); } using (var recorder = new SKPictureRecorder()) { var image = SKImage.FromEncodedData(path); var rect = new SKRect(0f, 0f, (float)image.Width, (float)image.Height); var canvas = recorder.BeginRecording(rect); canvas.DrawImage(image, rect); return(recorder.EndRecording()); } }
public override void DrawRect(CGRect dirtyRect) { var scaleFactor = Window.BackingScaleFactor; var skPictureRecorder = new SKPictureRecorder(); // TODO: Can we restrict the culling rect here? SKRect skCullingRect = SKRect.Create(float.MinValue, float.MinValue, float.MaxValue, float.MaxValue); SKCanvas canvas = skPictureRecorder.BeginRecording(skCullingRect); DrawingContext childContext = new(canvas); renderOrder = new(); childContext.Push(Matrix.Scale((float)scaleFactor, (float)scaleFactor)); Render(childContext); SKPicture render = skPictureRecorder.EndRecording(); var viewToIndex = renderOrder .Select((view, idx) => (view, idx)) .ToDictionary(item => item.Item1, item => item.Item2); if (content != null) { viewToIndex[content] = -1; } var totalViews = viewToIndex.Count; SortSubviews((a, b) => { if (!viewToIndex.TryGetValue(a, out var aidx)) { aidx = totalViews; } if (!viewToIndex.TryGetValue(b, out var bidx)) { bidx = totalViews; } var cmp = aidx - bidx; if (cmp < 0) { return(NSComparisonResult.Ascending); } else if (cmp > 0) { return(NSComparisonResult.Descending); } else { return(NSComparisonResult.Same); } }); if (childContext.IsVisible) { if (content == null) { content = new(); AddSubview(content, NSWindowOrderingMode.Below, null); } } if (content != null) { content.ContentsScale = scaleFactor; content.Render = render; content.Frame = Bounds; content.Layer.SetNeedsDisplay(); } }
/// <summary> /// Update content for single and detail /// </summary> public static void UpdateContent(CalloutStyle callout) { if (callout.Type == CalloutType.Custom) { return; } if (callout.Title == null) { callout.Content = -1; return; } var styleSubtitle = new Topten.RichTextKit.Style(); var styleTitle = new Topten.RichTextKit.Style(); var textBlockTitle = new TextBlock(); var textBlockSubtitle = new TextBlock(); if (callout.Type == CalloutType.Detail) { styleSubtitle.FontFamily = callout.SubtitleFont.FontFamily; styleSubtitle.FontSize = (float)callout.SubtitleFont.Size; styleSubtitle.FontItalic = callout.SubtitleFont.Italic; styleSubtitle.FontWeight = callout.SubtitleFont.Bold ? 700 : 400; styleSubtitle.TextColor = callout.SubtitleFontColor.ToSkia(); textBlockSubtitle.AddText(callout.Subtitle, styleSubtitle); textBlockSubtitle.Alignment = callout.SubtitleTextAlignment.ToRichTextKit(); } styleTitle.FontFamily = callout.TitleFont.FontFamily; styleTitle.FontSize = (float)callout.TitleFont.Size; styleTitle.FontItalic = callout.TitleFont.Italic; styleTitle.FontWeight = callout.TitleFont.Bold ? 700 : 400; styleTitle.TextColor = callout.TitleFontColor.ToSkia(); textBlockTitle.Alignment = callout.TitleTextAlignment.ToRichTextKit(); textBlockTitle.AddText(callout.Title, styleTitle); textBlockTitle.MaxWidth = textBlockSubtitle.MaxWidth = (float)callout.MaxWidth; // Layout TextBlocks textBlockTitle.Layout(); textBlockSubtitle.Layout(); // Get sizes var width = Math.Max(textBlockTitle.MeasuredWidth, textBlockSubtitle.MeasuredWidth); var height = textBlockTitle.MeasuredHeight + (callout.Type == CalloutType.Detail ? textBlockSubtitle.MeasuredHeight + (float)callout.Spacing : 0f); // Now we have the correct width, so make a new layout cycle for text alignment textBlockTitle.MaxWidth = textBlockSubtitle.MaxWidth = width; textBlockTitle.Layout(); textBlockSubtitle.Layout(); // Create bitmap from TextBlock using (var rec = new SKPictureRecorder()) using (var canvas = rec.BeginRecording(new SKRect(0, 0, width, height))) { // Draw text to canvas textBlockTitle.Paint(canvas, new TextPaintOptions() { IsAntialias = true }); if (callout.Type == CalloutType.Detail) { textBlockSubtitle.Paint(canvas, new SKPoint(0, textBlockTitle.MeasuredHeight + (float)callout.Spacing), new TextPaintOptions() { IsAntialias = true }); } // Create a SKPicture from canvas var picture = rec.EndRecording(); if (callout.InternalContent >= 0) { BitmapRegistry.Instance.Set(callout.InternalContent, picture); } else { callout.InternalContent = BitmapRegistry.Instance.Register(picture); } callout.Content = callout.InternalContent; } }
private SKPicture Load(XDocument xdoc) { var svg = xdoc.Root; var ns = svg.Name.Namespace; // find the defs (gradients) - and follow all hrefs foreach (var d in svg.Descendants()) { var id = d.Attribute("id")?.Value?.Trim(); if (!string.IsNullOrEmpty(id)) { defs[id] = ReadDefinition(d); } } Version = svg.Attribute("version")?.Value; Title = svg.Element(ns + "title")?.Value; Description = svg.Element(ns + "desc")?.Value ?? svg.Element(ns + "description")?.Value; // TODO: parse the "preserveAspectRatio" values properly var preserveAspectRatio = svg.Attribute("preserveAspectRatio")?.Value; // get the SVG dimensions var viewBoxA = svg.Attribute("viewBox") ?? svg.Attribute("viewPort"); if (viewBoxA != null) { ViewBox = ReadRectangle(viewBoxA.Value); } if (CanvasSize.IsEmpty) { // get the user dimensions var widthA = svg.Attribute("width"); var heightA = svg.Attribute("height"); var width = ReadNumber(widthA); var height = ReadNumber(heightA); var size = new SKSize(width, height); if (widthA == null) { size.Width = ViewBox.Width; } else if (widthA.Value.Contains("%")) { size.Width *= ViewBox.Width; } if (heightA == null) { size.Height = ViewBox.Height; } else if (heightA != null && heightA.Value.Contains("%")) { size.Height *= ViewBox.Height; } // set the property CanvasSize = size; } // create the picture from the elements using (var recorder = new SKPictureRecorder()) using (var canvas = recorder.BeginRecording(SKRect.Create(CanvasSize))) { // if there is no viewbox, then we don't do anything, otherwise // scale the SVG dimensions to fit inside the user dimensions if (!ViewBox.IsEmpty && (ViewBox.Width != CanvasSize.Width || ViewBox.Height != CanvasSize.Height)) { if (preserveAspectRatio == "none") { canvas.Scale(CanvasSize.Width / ViewBox.Width, CanvasSize.Height / ViewBox.Height); } else { // TODO: just center scale for now var scale = Math.Min(CanvasSize.Width / ViewBox.Width, CanvasSize.Height / ViewBox.Height); var centered = SKRect.Create(CanvasSize).AspectFit(ViewBox.Size); canvas.Translate(centered.Left, centered.Top); canvas.Scale(scale, scale); } } // translate the canvas by the viewBox origin canvas.Translate(-ViewBox.Left, -ViewBox.Top); // if the viewbox was specified, then crop to that if (!ViewBox.IsEmpty) { canvas.ClipRect(ViewBox); } LoadElements(svg.Elements(), canvas); Picture = recorder.EndRecording(); } return(Picture); }
private static unsafe void DrawWaves(ThumbnailsRenderContext ctx, MediaStream audioStream) { var height = 88; var width = 88; using var recorder = new SKPictureRecorder(); using var canvas = recorder.BeginRecording(SKRect.Create(width, height)); var columnCount = 88 * 2; var columnWidth = (float)width / columnCount; using var wavePaint = new SKPaint { Color = new SKColor(128, 128, 128, 76), StrokeWidth = columnWidth }; var totalSample = audioStream.SampleRate * audioStream.Duration; var columnMaxSample = (int)(totalSample / columnCount); var columns = new short[columnCount]; using var decoder = audioStream.CreateStreamDecoder(); using var filter = new AudioFormatFilter("sample_fmts=s16:channel_layouts=mono", audioStream, decoder); filter.Build(); long sum = 0; var n = 0; var c = 0; while (filter.MoveNext()) { var frame = filter.Current.Value; var p = (short *)frame->data[0]; for (var i = 0; i < frame->nb_samples; i++) { sum += SampleAbs(p[i]); n++; if (n == columnMaxSample && c < columnCount) { columns[c] = (short)(sum / n); n = 0; sum = 0; c++; } } } for (var i = 0; i < columnCount; i++) { var h = Math.Max((float)columns[i] * height / short.MaxValue, 0.5f); var x = i * columnWidth; canvas.DrawLine(x, (height - h) / 2.0f, x, (height + h) / 2.0f, wavePaint); } _cachedWaveformDecorationImage ??= SKImage.FromEncodedData(ReadWaveformDecorationImage()); canvas.DrawImage(_cachedWaveformDecorationImage, SKRect.Create((width - 28) / 2.0f, (height - 36) / 2.0f, 28, 36)); using var picture = recorder.EndRecording(); ThumbnailUtils.DrawShadowView( ctx, new SkPictureView( picture, new SKSize(88, 88))); }