[英]Direct 2D SVG Rendering in UWP
我正在嘗試在https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/D2DSvgImage改編Direct 2D SVG示例以繪制SVG字符串,而不是從文件中繪制。 我所做的就是替換代碼以從Assets文件打開流。 以下是相關摘錄:
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
)
);
});
}
但是我總是得到莫名其妙的參數錯誤異常,並且無法調試為什么會出現這種情況。 (DirectX不附帶任何調試或提供提示的原因以及哪個參數不正確!)。
我的有根據的猜測是,API從未告訴過我們一個隱藏的事實,即嚴格禁止在CreateSvgDocument
中使用InMemoryRandomAccessStream
。 我怎樣才能解決這個問題?
在引發異常之前,此代碼將發出以下診斷信息:
D2D調試錯誤-解析SVG文檔時遇到錯誤。
當我嘗試讀取流內容時,我發現它已關閉(通過在下一個lambda中調用stream->Position;
), 實際上該內容不存在 。 然后,我研究了文檔。 從DataWriter::Close
方法參考 :
備注
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他們應該為構造函數寫那句話...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.