user3743210
user3743210

Reputation: 211

How to load an svg to CanvasVirtualControl in C++/winrt?

I've been loading drawing svg images successfully in a UWP app built with C++/winrt but in the latest release find that the call to load the svg throws an exception. The crash happens in an IAsync method that is hard to trace, but I've narrowed the problem down to the one line that loads the SVG.

This is normally looping to read lots of files, but very simple reduction of the problem still displays the issue:

winrt::Microsoft::Graphics::Canvas::UI::Xaml::CanvasVirtualControl resourceCreator
winrt::Windows::Storage::StorageFile nextFile = nullptr;
winrt::Microsoft::Graphics::Canvas::Svg::CanvasSvgDocument nextSvg = nullptr;
winrt::Windows::Storage::Streams::IRandomAccessStream  fileStream = nullptr;

//This is called from within the lambda handling CreateResources for the CanvasVirtualControl
//The VirtualControl is provided as the resourceCreator argument

IAsyncAction loadSVGs(winrt::Microsoft::Graphics::Canvas::UI::Xaml::CanvasVirtualControl resourceCreator)
{
nextFile = m_symbol_resource_files.GetAt(i);
fileStream = co_await nextFile.OpenReadAsync();
nextSvg = co_await CanvasSvgDocument::LoadAsync(resourceCreator,fileStream);
}

The call to LoadAsync fails with

exception: winrt:hresult_invalid_argument at memory location 0x0C93F1CB
void resume()const{
->_coro_resume(_Ptr);
}

If I continue past the exception I find that the resource has in fact loaded and is usable. But if running outside Visual Studio the app will often quit at this line. Could it be that the CanvasVirtualControl is not acceptable?

Or is there a better way to load the svg from file? I haven't been able to work out the CanvasDocument's LoadFromXML, as it takes a System.String argument not available in C++/winrt and the winrt std::wstring is not acceptable as a substitute [Correction: in fact hstring will work as an argument and that can be created from std::wstring].

[Update]I have not yet created a simple demo project displaying this behavior, but I think I have a line on the cause and would like to extend my question. I've tried both the LoadFromXml and the LoadAsync methods of the CanvasSvgDocument, and the second of these used to be fine, but now both fail the same way and it seems to me that the ResourceCreator argument may be the trouble. I am creating these resources in the CreateResources handler and I pass the sender - CanvasVirtualControl - as the resourceCreator. The listed argument for both the CanvasSvgDocument calls, however, is ICanvasResourceCreator. I had thought this was a convenience and that the CanvasVirtualControl could be passed directly for that argument (and so it used to be). But perhaps this is incorrect, maybe always was and is now being noticed as incorrect? If so, how would the sender in the CreateResources handler properly be passed to the CanvasSvgDocument method?

Upvotes: 0

Views: 393

Answers (1)

Faywang - MSFT
Faywang - MSFT

Reputation: 5868

I created a blank app to use CanvasVirtualControl to load SVG, it worked well. Can you provide a simple sample that can be reproduced? And I checked the LoadFromXML method, the parameter it needs is hstring type instead of System.String.

In addition, about loading the svg from file, do you have to use win2d to load svg? If not, you could try to use Image control by SvgImageSource to load svg, like below:

.xaml:

<Image x:Name="MyImage" Width="300" Height="200"></Image>

.cpp:

winrt::Windows::Storage::StorageFile nextFile = nullptr;
winrt::Microsoft::Graphics::Canvas::Svg::CanvasSvgDocument nextSvg = nullptr;
winrt::Windows::Storage::Streams::IRandomAccessStream  fileStream = nullptr;

nextFile = co_await KnownFolders::PicturesLibrary().GetFileAsync(L"Freesample.svg");
fileStream = co_await nextFile.OpenReadAsync();

SvgImageSource sourcee = SvgImageSource();
co_await sourcee.SetSourceAsync(fileStream);
MyImage().Source(sourcee); 

Upvotes: 1

Related Questions