2017-10-12 8 views
0

J'essaie d'adapter l'échantillon SVG direct 2D à https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/D2DSvgImage pour dessiner une chaîne SVG au lieu d'un fichier. Tout ce que j'ai fait était de remplacer le code pour ouvrir un flux à partir d'un fichier Assets. Voici l'extrait pertinent:Rendu 2D direct SVG dans UWP

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 
       ) 
      ); 
    }); 
} 

Mais je suis toujours reçois le inexplicable Le paramètre est incorrect exception et il n'y a aucun moyen de déboguer la raison pour laquelle il est le cas. (DirectX ne vient pas avec un moyen de déboguer ou de fournir toute indication pourquoi et quel paramètre est incorrect !?)

Ma supposition est que l'API ne nous dira jamais caché le fait que l'utilisation InMemoryRandomAccessStream dans CreateSvgDocument est strictement interdite . Comment puis-je réparer cela?

+0

A quel point êtes-vous cette exception? – VTT

+0

Le second ThrowIfFailed, c'est-à-dire l'appel à CreateSvgDocument. Je peux confirmer que l'iStream dans l'appel précédent a un contenu correct. –

+0

Il semble que vous n'ayez pas encore fini d'écrire. Vous devrez peut-être appeler 'writer.StoreAsync()' puis 'writer.FlushAsync()' comme décrit dans l'exemple d'utilisation de la classe ['InMemoryRandomAccessStream'] (https://docs.microsoft.com/en-us/uwp/api /Windows.Storage.Streams.InMemoryRandomAccessStream). – VTT

Répondre

0

Avant de jeter exception ce code émet le diagnostic suivant:

D2D DEBUG erreur - Une erreur est survenue lors de l'analyse d'un document SVG.

Lorsque j'ai essayé de lire le contenu de flux que j'ai compris qu'il est fermé (en appelant stream->Position; dans la prochaine lambda), qui est le contenu est en fait pas là. Ensuite, j'ai regardé dans docs. De DataWriter::Close method reference:

Remarques

DataWriter prend possession du flux qui est passé à son constructeur. L'appel de cette méthode appelle également le flux associé. Après l'appel de cette méthode, les appels à la plupart des autres méthodes DataWriter échouent. Si vous ne souhaitez pas que le flux associé soit fermé lorsque le lecteur se ferme, appelez le DataWriter.DetachStream avant d'appeler cette méthode.

Donc, dans votre exemple writer sera Closestream quand il est hors de portée et analyseur SVG ne sera pas capable de lire quoi que ce soit. Donc, votre code devrait ressembler à ceci:

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 Ils auraient dû écrit cette remarque pour le constructeur ...