2017-10-12 73 views
0

我試圖在https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/D2DSvgImage上修改Direct 2D SVG示例來繪製SVG字符串,而不是從文件中繪製。我所做的只是替換代碼以從資產文件打開流。下面是相關的摘錄:UWP中的直接2D SVG渲染

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嚴禁 。我怎樣才能解決這個問題?

+0

在這一點你得到這個例外? – VTT

+0

第二個ThrowIfFailed,即對CreateSvgDocument的調用。我可以確認前一次調用中的iStream具有正確的內容。 –

+0

看來你還沒寫完。您可能需要按照['InMemoryRandomAccessStream'類用法示例](https://docs.microsoft.com/zh-cn/uwp/api)中所述調用'writer.StoreAsync()',然後調用'writer.FlushAsync() /Windows.Storage.Streams.InMemoryRandomAccessStream)。 – VTT

回答

0

拋出異常之前,此代碼發出如下診斷:

D2D調試錯誤 - 在解析SVG文檔時遇到錯誤。

當我試圖(通過調用在接下來的拉姆達stream->Position;)來讀取流的內容我已經想通了,它是封閉的,那就是內容其實並不存在是。然後我查看了文檔。從DataWriter::Close method reference

備註

DataWriter需要傳遞給它的構造流的所有權。調用此方法也會調用關聯的流。調用此方法後,調用大多數其他DataWriter方法將失敗。 如果您不希望讀取器關閉時關閉關聯的流,請在調用此方法之前調用DataWriter.DetachStream

所以,在你的榜樣writerClosestream當它超出範圍和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他們應該已經寫了這句話的構造......