我正在尝试在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
严格禁止的隐藏事实。我该如何解决这个问题?
答案 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他们应该为构造函数写下这句话......