在UWP中直接2D SVG渲染

时间:2017-10-12 04:09:06

标签: c++ uwp directx

我正在尝试在https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/D2DSvgImage调整Direct 2D SVG样本来绘制SVG字符串而不是文件。我所做的就是替换代码以从Assets文件中打开一个流。以下是相关摘录:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs/Observable';

interface ItemsResponseObj {
    id: string,
    modified: string,
    name: string
}

interface ItemsResponse {
    shows: Array<ItemsResponseObj>;
}

@Injectable()
export class AppService {

    constructor(private http: HttpClient) { }

    getData(): Observable<ItemsResponse> {
        return this.http.get<ItemsResponse>('api/api-data.json')
    }

}

但我总是得到莫名其妙的参数不正确异常,并且没有办法调试为什么会这样。 (DirectX没有任何方式来调试或提供任何提示,为什么以及哪个参数不正确!?)

我的猜测是,API从未告诉我们在void D2DSvgImageRenderer::CreateDeviceDependentResources() { auto d2dContext = m_deviceResources->GetD2DDeviceContext(); StorageFolder^ packageFolder = Windows::ApplicationModel::Package::Current->InstalledLocation; // Retrieve the SVG file from the app package. // ORIGINAL create_task(packageFolder->GetFileAsync("Assets\\drawing.svg")).then([=](StorageFile^ file) create_task([]() { // Open the SVG file for reading. // ORIGINAL return file->OpenAsync(FileAccessMode::Read); char *svg = "<svg><circle r=\"300\" cy=\"509\" cx=\"370\" style=\"fill:#ffff00;stroke:#000000;stroke-width:5\"/></svg>"; auto stream = ref new Windows::Storage::Streams::InMemoryRandomAccessStream(); auto writer = ref new Windows::Storage::Streams::DataWriter(stream); auto p = svg; while (*p != '\0') { writer->WriteByte((unsigned char)*p); p++; } create_task(writer->StoreAsync()).get(); create_task(writer->FlushAsync()).get(); return stream; }).then([=](IRandomAccessStream^ stream) { // Wrap the WinRT stream with a COM stream. ComPtr<IStream> iStream; DX::ThrowIfFailed( CreateStreamOverRandomAccessStream( stream, IID_PPV_ARGS(&iStream) ) ); // Parse the file stream into an SVG document. DX::ThrowIfFailed( d2dContext->CreateSvgDocument( iStream.Get(), D2D1::SizeF(sc_svgSize, sc_svgSize), // Create the document at a size of 500x500 DIPs. &m_svgDocument ) ); }); } 中使用InMemoryRandomAccessStream 严格禁止的隐藏事实。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

在抛出异常之前,此代码会发出以下诊断:

  

D2D DEBUG ERROR - 解析SVG文档时遇到错误。

当我尝试阅读流内容时,我发现它已关闭(通过在下一个lambda中调用stream->Position;),即内容实际上不存在 。然后我查看了文档。来自DataWriter::Close method reference

  

<强>说明

     

DataWriter获取传递给其构造函数的流的所有权。调用此方法还会调用关联的流。调用此方法后,对大多数其他DataWriter方法的调用将失败。   如果您不希望在阅读器关闭时关闭关联的流,请在调用此方法之前调用DataWriter.DetachStream

因此,在您的示例中writer Close stream当它超出范围且SVG解析器无法读取任何内容时。所以你的代码应该是这样的:

auto stream{ref new Windows::Storage::Streams::InMemoryRandomAccessStream{}};
auto writer{ref new Windows::Storage::Streams::DataWriter{stream}}; // takes ownership of stream
const auto & sz_svg{"<svg><circle r=\"300\" cy=\"509\" cx=\"370\" style=\"fill:#ffff00;stroke:#000000;stroke-width:5\"/></svg>"};
for(const char * p{sz_svg}; '\0' != *p; ++p)
{
    writer->WriteByte(static_cast< unsigned char >(*p));
}
create_task(writer->StoreAsync()).get(); // mandatory
//create_task(writer->FlushAsync()).get(); // not necessary since underlaying memory stream does not require flushing
writer->DetachStream(); // release ownership of stream, the value returned is not used since we already have stream variable

PS他们应该为构造函数写下这句话......