首页 > 解决方案 > 如何从文件中加载 CanvasSvgDocument?

问题描述

在 C++/winrt 项目中,我有大量要从文件加载的小型 svg 资源。由于在 CanvasVirtualControl 的每个 CreateResources 事件中从磁盘重新加载它们会很慢,因此我提前加载了它们并将每个数据存储在一个数组中。当 CreateResources 发生时,我的意图是使用 CanvasSvgDocument 方法 LoadFromXml(System.string) 为其中的每一个加载一个 CanvasSvgDocument。但是,如果我使用资源创建器创建 svgDocument,则在调用 LoadFromXml() 时会出现无效参数崩溃。resourceCreator 参数看起来正确(VS 预览版 6 现在允许我查看局部变量!)并且 xml 数据字符串参数看起来像有效的 svg 数据,所以我对崩溃的最佳猜测是数据字符串的格式错误。文件数据为 UTF-8。如果我将其转换为 std:: wstring 我必须为 LoadFromXml 参数它仍然可以理解为字节数据吗?例如,我以这种方式创建 std::wstring,给定一个指向 unsigned char 文件数据的指针及其以字节为单位的长度:

m_data_string = std::wstring(data, data + dataLength);

当触发 CreateResources 时,以这种方式引用数据字符串:

m_svg = CanvasSvgDocument(resourceCreator);
m_svg.LoadFromXml(resourceCreator, m_data_string);

但是 LoadFromXml 因无效参数错误而崩溃。我看到数据字符串的长度是正确的,但当然是字符数,而不是数据的实际大小。svg 中的 UTF-8 属性与现在记录为 16 位字符的事实之间是否存在冲突?如果是这样,如何从此类数据中加载 xml 文档?

[更新] 建议我使用 winrt::to_hstring。我将 unsigned char 数据读入 std::string,

std::string cstring = std::string("");
cstring.assign(data, data + dataLength);

然后我将其转换为:

m_data_string = winrt::to_hstring(cstring);

最后尝试像以前一样加载一个svg:

m_svg.LoadFromXml(resourceCreator, m_data_string);

它像以前一样崩溃。我注意到在这两种情况下转换字符串的调试器似乎都是乱码 - 在这两种情况下,它都在调试器中读取为预期的 svg 数据。但是,如果这个 hstring 是宽字符,那会不会与 svg 中将其标识为 UTF-8 的属性发生冲突?

[更新] 我开始怀疑是否有人曾经使用过 CanvasSvgDocument.Draw() 来绘制从文件加载的 svg。这些文件现在正在加载而不会崩溃,而不会对其内部编码参考进行任何更改。但是——他们不会画画。这些文件(其中 239 个)是 UTF-8、svg 1.1,如果在 Edge 或任何浏览器中打开,它们会很好地显示。但是,如果我将文件数据加载到 hstring,创建 CanvasSvgDocument,然后使用 CanvasSvgDocument.LoadFromXml 加载它们,它们在被 CanvasSvgDocument 的 draw 方法调用时不会绘制。在绘图过程中,其他形状的绘图等工作正常。这可能是一个提示:如果我在加载其中一个 svg 后调用 GetXML(),则返回的是这样的:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>

即,绘图信息不存在。或者这是 GetXml() 想要返回的全部内容?那似乎没有用。所以也许 CanvasSvgDocument.LoadFromXml(ResourceCreator, String) 实际上还没有工作?所以我又问了一遍:有没有办法从文件数据中加载一个功能性的 CanvasSvgDocument ?

标签: c++-winrtwin2d

解决方案


我在这里的第一个答案是错误的:我上面的代码中的错误是 LoadFromXml() 是一个静态方法,有人在别处向我指出,我正在丢弃返回的结果。它应该是 theSvg = CanvasSvgDocument::LoadFromXml(string)。纠正了这一点,我又回到了在参数是宽字符串的方法中加载 UTF-8 数据的问题。毕竟将内部引用更改为 UTF-16 并没有帮助。使用 CanvasSvgDocument::LoadAsync(filestream) 加载 svg 是可行的,但如果我想在不重新访问磁盘的情况下加载它们,我需要找到一种方法从字节缓冲区中生成 RandomAccessFileStream,然后使用 LoadAsync。我认为。除非有其他方法可以使 LoadFromXmL() 工作 - 目前它失败并出现无效参数错误。


推荐阅读