Code Monkey home page Code Monkey logo

svgforxaml's Introduction

Svg for Xaml Library

NuGet Downloads License

Draw images from svg file with Win2D.

app screenshot

Tokyo railmaps

app screenshot

Thanks to railmaps

Requirement

Usage

xaml with binding

Binding content type is SvgDocument.

<svg:SvgImage Content="{Binding ...}" />

Renderer a raster image from svg image

var svg = SvgDocument.Parse(...);
var uri = new Uri("ms-appdata:///local/filename.jpg");
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
await SvgImageRenderer.RendererImageAsync(file, new SvgImageRendererSettings()
{
	Document = svg,
	Format = SvgImageRendererFileFormat.Jpeg,
	Scaling = 10.0F,
	Quality = 0.8F,
});

Rendering in Win2D ecosystem

var svg = SvgDocument.Parse(...);

var width = 24.0F;
var height = 24.0F;
var scaling = 3.0F;
var device = CanvasDevice.GetSharedDevice();
using (var offScreen = new CanvasRenderTarget(device, width, height, scaling * 96.0F))
using (var renderer = new Win2dRenderer(offScreen, svg))
using (var session = offScreen.CreateDrawingSession())
{
	session.Clear(Colors.Transparent);
	renderer.Renderer(width, height, session); // <- rendering svg content
}

Note

If you build your app for Windows 10 Aniversary Update or later, you should use SVG API on Direct2D.

LICENSE

MIT License

Author

svgforxaml's People

Contributors

mntone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svgforxaml's Issues

svd path d syntax

The grammar allows for x.y.z as two floating point numbers. But I get a format error with SvgForXaml.

for the string 'M 0.6.5', the first coordinate of the "moveto" consumes the characters "0.6" and stops upon encountering the second decimal point because the production of a "coordinate" only allows one decimal point. The result is that the first coordinate will be "0.6" and the second coordinate will be ".5".

Performance?

Hi,
I really like your project and would like to use in the context of a Win2D application. Have you done some performance measurements. I had a look to the Win2DRenderer and realized that there are a lot of transformations from svg to win2d objects and allocations, which might hurt performance. It is probably fine with the SvgImage control, because it renders the svg's less often and creates a reusable buffer but it might hurt when you draw large svgs and use something like the VirtualCanvasControl or when you render it inside a custom win2d session.

Nuget package?

Great library. Is there a plan for making a Nuget package?

Thanks!

Issues with rendering when using ItemsSource

I've been trying to use ItemsSource property of a ListView to render a bunch of SVG images and had no luck. After debugging it a bit, I think there is an issue with SvgImage class.

Consider this xaml:

<Grid Background="Purple">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <ListView x:Name="SvgForXamlListView">
        <ListView.ItemTemplate>
            <DataTemplate x:Key="SvgForXamlDataTemplate">
                <svg:SvgImage Margin="10" Width="100" Height="100" Content="{Binding Document}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

    <StackPanel Orientation="Horizontal" Grid.Row="1">
        <Button Content="Draw" Click="OnDrawClick" />
        <Button Content="Navigate" Click="OnNavigateClick" />
    </StackPanel>
</Grid>

And this code-behind:

public sealed partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private async void OnDrawClick(object sender, RoutedEventArgs e)
    {
        var svgFiles = new []
        {
            "ms-appx:///Assets/test1.svg",
            "ms-appx:///Assets/test2.svg",
            "ms-appx:///Assets/test3.svg",
            "ms-appx:///Assets/test4.svg"
        };

        var viewModels = new List<SvgImageViewModel>();
        foreach (var svgFile in svgFiles)
        {
            var viewModel = new SvgImageViewModel();
            await viewModel.InitializeAsync(svgFile);
            viewModels.Add(viewModel);
        }

        SvgForXamlListView.ItemsSource = viewModels;
    }

    private void OnNavigateClick(object sender, RoutedEventArgs e)
    {
        Frame.Navigate(typeof(Page2));
    }
}

public class SvgImageViewModel
{
    public Uri SvgUri { get; private set; }

    public SvgDocument Document { get; private set; }

    public async Task InitializeAsync(string fileUri)
    {
        this.SvgUri = new Uri(fileUri);

        var file = await StorageFile.GetFileFromApplicationUriAsync(SvgUri);

        using (var stream = await file.OpenStreamForReadAsync())
        using (var reader = new StreamReader(stream))
        {
            var xml = new XmlDocument();
            xml.LoadXml(reader.ReadToEnd(), new XmlLoadSettings { ProhibitDtd = false });
            var svgDocument = SvgDocument.Parse(xml);
            this.Document = svgDocument;
        }
    }
}

The above does not render anything on the screen. Even though it does create 4 instances of SvgImage controls and places them in the UI tree, the CanvasControl does not render anything. Debugging through this I see that when using ItemsSource, SvgImage.OnContentChanged is called before SvgImage.OnApplyTemplate. Therefore at the time that content is being applied, _canvasControl instance is NULL and so _renderer is not created.

Making the following change to the constructor of SvgImage resolves this problem because it ensures that the control will render its content after it is loaded, and then also whenever the content changes thereafter. It also takes care of safely unloading the underlying CanvasControl whenever SvgImage is unloaded:

public SvgImage()
    : base()
{
    this.DefaultStyleKey = typeof(SvgImage);
    Loaded += (sender, args) => OnContentChanged(this.Content);
    Unloaded += (sender, args) => SafeUnload();
}

If this sounds like a correct fix to your SVG viewer then I can make a pull request against your repository with my suggested fixes.

Texts disappeared while converting to PNG

First of all, thanks for putting effort on this excellent lib. It really helped me a lot!

I'm trying to convert some SVG files to PNG however at some point during the conversion all texts in the images disappear. Do you have an idea of what could be the problem?

I've attached a sample SVG file where the problem happens.

test.svg.txt

Loading Font Awesome SVG Exception: Object reference not set to an instance of an object.

I am trying to render this file:
500px.zip

This is my Code Xaml:
<svg:SvgImage x:Name="SvgPreview" Grid.Row="2" />

This is my code C#:
await SvgPreview.LoadFileAsync(mediaModel.MediaFile);

This is the stacktrace:

   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseSmoothQuadraticBezierCurveToArgumentSequence(StringPtr ptr, Boolean abs)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseSmoothQuadraticBezierCurveToArgumentSequence(StringPtr ptr, Boolean abs)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseSmoothQuadraticBezierCurveToArgumentSequence(StringPtr ptr, Boolean abs)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseSmoothQuadraticBezierCurveToArgumentSequence(StringPtr ptr, Boolean abs)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseSmoothQuadraticBezierCurveTo(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseDrawToCommand(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseDrawToCommands(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseDrawToCommands(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseMoveToDrawToCommandGroup(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseMoveToDrawToCommandGroups(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseMoveToDrawToCommandGroups(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseMoveToDrawToCommandGroups(StringPtr ptr)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser..ctor(String pathData)
   at Mntone.SvgForXaml.Path.SvgPathSegmentParser.Parse(String pathData)
   at Mntone.SvgForXaml.Path.SvgPathElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgElement.ParseChildren(INode parent, XmlNodeList nodes)
   at Mntone.SvgForXaml.SvgElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgSvgElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgDocument.Parse(XmlDocument document)
   at presenter.uwp.MainPage.<LstMediaFiles_ItemClick>d__14.MoveNext()

fill and fill-rule for grouped

I use Sketch app to export SVG file.
When this app exports as SVG, the place for fill and fill-rule is different by being grouped or not grouped.
if grouped,
<g id="man-with-pen" transform="translate(66.500000, 11.799999)" fill-rule="nonzero" fill="#FFFFFF"> <path d="M24.9972378,31.5623524 C25.64362,31.7042296 26.2659459,31.9244344 26.8409428,32.2203132 C27.8347132,32.731682 28.6576994,33.4926622 29.9119051,34.8990007 C31.5714499,36.7598453 31.8665677,37.0577507 32.4386752,37.3393474 C33.9812679,38.0986262 35.3133223,38.2713557 37.8291619,38.0136942 L38,40.0049651 C35.1915506,40.2925945 33.5494459,40.0796602 31.6868031,39.1628498 C30.7966636,38.7247147 30.508832,38.4341643 28.6008581,36.2947567 C27.4941564,35.0538141 26.7951214,34.4074463 26.0609982,34.0296853 C25.5734205,33.7787903 25.0376839,33.5992184 24.4800364,33.4925743 L24.9972378,31.5623524 L24.9972378,31.5623524 Z" id="Combined-Shape"></path>
if not grouped
<path d="M91.4972378,43.3623516 C92.14362,43.5042288 92.7659459,43.7244337 93.3409428,44.0203124 C94.3347132,44.5316812 95.1576994,45.2926614 96.4119051,46.699 C98.0714499,48.5598445 98.3665677,48.85775 98.9386752,49.1393467 C100.481268,49.8986254 101.813322,50.071355 104.329162,49.8136934 L104.5,51.8049643 C101.691551,52.0925937 100.049446,51.8796594 98.1868031,50.9628491 C97.2966636,50.524714 97.008832,50.2341636 95.1008581,48.0947559 C93.9941564,46.8538133 93.2951214,46.2074456 92.5609982,45.8296845 C92.0734205,45.5787895 91.5376839,45.3992176 90.9800364,45.2925736 L91.4972378,43.3623516 L91.4972378,43.3623516 Z" id="Combined-Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
I'm not sure this behavior is fit to SVG specification or not, but this causes grouped path is drawn as filling black by this library.

Support ARM64

Why trying to add support for ARM64 to my UWP projects, I get this:

image

I am happy to contribute with a PR, but need to know whether you will release a new version.

Thanks!

Question about inheritance.

Hi.
This is the most feature-rich SVG solution on WinRT as far as I searched.

I wonder it never inherits the properties of 'fill' and 'stroke',
although should do according to the specification
and some actual images suppose this like the SVG tiger.
Could you tell me?

Thank you.

Dictionary is not checked for duplicate keys

An item with the same key has already been added. Key: 'MyKey'

Call stack:

   at System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(Object key)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at Mntone.SvgForXaml.SvgElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgGroupElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgElement.ParseChildren(INode parent, XmlNodeList nodes)
   at Mntone.SvgForXaml.SvgElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgGroupElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgElement.ParseChildren(INode parent, XmlNodeList nodes)
   at Mntone.SvgForXaml.SvgElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgSvgElement..ctor(INode parent, XmlElement element)
   at Mntone.SvgForXaml.SvgDocument.Parse(XmlDocument document)
   at Mntone.SvgForXaml.SvgDocument.Parse(String document)
   at Mntone.SvgForXaml.SvgDocument.Parse(Byte[] document)

Is it forbidden in svg formats to use duplicate names? If not, I am happy to provide a PR, but need to be sure you will be releasing a new version with this PR.

Other apps (e.g. Inkscape) can parse and display this svg correctly. I think id's should be managed on parent level, not on document level (basically every SvgElement could / should have a dictionary with id's).

Index was outside the bounds of array on get_Char()

at Mntone.SvgForXaml.Internal.StringPtr.get_Char()
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseCommaOrWhitespace(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseCurveToArgumentSequence(StringPtr ptr, Boolean abs)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseCurveTo(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseDrawToCommand(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseDrawToCommands(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseDrawToCommands(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseDrawToCommands(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseMoveToDrawToCommandGroup(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.ParseMoveToDrawToCommandGroups(StringPtr ptr)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser..ctor(String pathData)
at Mntone.SvgForXaml.Path.SvgPathSegmentParser.Parse(String pathData)
at Mntone.SvgForXaml.Path.SvgPathElement..ctor(INode parent, XmlElement element)
at Mntone.SvgForXaml.SvgElement.ParseChildren(INode parent, XmlNodeList nodes)
at Mntone.SvgForXaml.SvgElement..ctor(INode parent, XmlElement element)
at Mntone.SvgForXaml.SvgGroupElement..ctor(INode parent, XmlElement element)
at Mntone.SvgForXaml.SvgElement.ParseChildren(INode parent, XmlNodeList nodes)
at Mntone.SvgForXaml.SvgElement..ctor(INode parent, XmlElement element)
at Mntone.SvgForXaml.SvgDefinitionsElement..ctor(INode parent, XmlElement element)
at Mntone.SvgForXaml.SvgElement.ParseChildren(INode parent, XmlNodeList nodes)
at Mntone.SvgForXaml.SvgElement..ctor(INode parent, XmlElement element)
at Mntone.SvgForXaml.SvgSvgElement..ctor(INode parent, XmlElement element)
at Mntone.SvgForXaml.SvgDocument.Parse(XmlDocument document)
at Mntone.SvgForXaml.UI.Xaml.SvgImage.d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at SvgForXamlTestApp.MainPage.d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at SvgForXamlTestApp.MainPage.<ButtonBase_OnClick>d__4.MoveNext()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.