Avalonia
Avalonia copied to clipboard
Allow custom DrawingContext implementations
Is your feature request related to a problem? Please describe.
We'd like to implement our own DrawingContext to provide our own export functionality. This would allow us to make certain Avalonia controls aware of our implementation so that it can inject additional context into the output when for example creating an svg or emf.
Describe the solution you'd like
public DrawingContext ctor protected instead of internal.
Describe alternatives you've considered
We've tried using the built in skia impementation to export to svg but it is not complete and does not allow us the same flexibility.
Additional context
No response
How would this API look like? I can't imagine. Are you referring to somehow extending rendering engine so it can support extra types?
Perhaps I'm missing something obvious, but I did a simple test and made the DrawingContext ctor protected instead of internal, built my own class inheriting from it and then rendered an Avalonia object using ImmediateRenderer.Render. I didn't do a complete implementation for my test, but for the operations I implemented it worked fine.
From what it sounds, this idea might conflict with our plans on drawing context related code.
ImmediateRenderer is going to be removed. Primarily because we are migrating to async CompositionRenderer, which can utilize GPU resources, unlikely ImmediateRenderer.
DrawingContext is protected since it's backend by a platform specific implementation (skia, d2d) or intermediate presentation of a context (anything that records draw calls, like a visual brush).
I can see overriding a DrawingContext can be useful to record draw calls yourself for any kind of statistics. IIRC, WPF allows that as well.
I don't think that ImmediateRenderer is the issue here, but rather the possibility to derive your own implementation from DrawingContext. It is currently not possible since the CTOR is "internal". It could still be backed by internal platform specific implementations.
DrawingContext is abstract by design so people can use it as a drawing operation sink
https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Base/Media/DrawingContext.cs
The internal ctor is wrong
cc @kekekeks
WPF has DrawingContext's .ctor to be internal too.
In general we are currently quite reluctant to make internal-ish classes to be user-implementable mostly because of backwards compatibility guarantees. I. e. adding new members to that class would break user implementations and we don't want to be blocked from adding those during 11.x.y lifecycle.
In WPF you can get a DrawingGroup from any Visual using VisualTreeHelper.GetDrawing. So to convert WPF element to some other format you can traverse the visual tree, get a drawing group for each visual and process the drawing groups since they mostly contains the most basic "building blocks" like GeometryDrawing, DrawingGroup, GlyphRunDrawing or ImageDrawing.
If you are reluctant to open up DrawingContext then perhaps something similar would be more feasible?
Will have to try, but maybe it is possible to use the existing API to accomplish something similar.
Traverse the visual tree, for each visual create a new DrawingGroup, and render the visual to the DrawingGroup using the context from DrawingGroup.Open.
Ok, that isn't possible right now either because Geometry.PlatformImpl is internal so there's no way to get the real geometries.
Ok, seems like it works by rendering each Geometry separately using a SKSvgCanvas and then replacing the fill and stroke attributes appropriately.