0
votes

I am working on an application that requires a server request for an SVG that is representative of a particular product configuration. This is my first time dealing with SVG and I am hung up on decoding the server response in such a way where the image can be displayed with a QSvgRenderer. Something like this

QByteArray panelData(QS.toStdString().c_str(), QS.length());
QSvgRenderer renderSVG(panelData);
QImage image(500, 200, QImage::Format_ARGB32);
QPainter painter(&image);
renderSVG.render(&painter);

I also thought about going the qpixmap on qlabel route like this.

QPixmap pix;
pix.fromImage(image);
ui->PixLabel->setPixmap(QPixmap::fromImage(image));

I have attempted using QTextdocument::toHtml as others have suggested but only end up trading one set of decoding problems for others. Do the qt libraries have a direct way of rendering the response below?

A server reply in part...

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg width="307px" height="625px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="P-mlvr" x1="0%" y1="0%" x2="0%" y2="100%"> <stop offset="0%" style="stop-color:#f0f0f0;stop-opacity:1;" /> <stop offset="0.0625" style="stop-color:#e0e0e0;stop-opacity:1;" /> <stop offset="100%" style="stop-color:#d0d0d0;stop-opacity:1;" /> </linearGradient> <linearGradient id="P-flvr" x1="0%" y1="100%" x2="0%" y2="0%"> <stop offset="0%" style="stop-color:#b0b0b0;stop-opacity:1;" /> <stop offset="0.0625" style="stop-color:#e0e0e0;stop-opacity:1;" /> <stop offset="75%" style="stop-color:#e0e0e0;stop-opacity:1;" /> <stop offset="100%" style="stop-color:#d0d0d0;stop-opacity:1;>

2
The string you're showing is a plain svg descriptor, if you manage to correctly extract it in QS your first code snippet seems legit: what's not working?MatG
The first thing I tried was feeding the above response directly into the SVG Renderer and all I got was a blank image. Maybe extracting to the QByteArray is incorrect.bluebass44
I have tried a number of variants of RenderSVG.load(panelData) changing the decoding of panelData. All return false.bluebass44
Just to see if there's a problem with encoding, can you try to take the QByteArray containing the svg (<xml ...<svg...</svg> part), save to file ex. test.svg and open it with a svg viewer (ex. browser) to check if it's valid?MatG
the server reply looks incomplete, or you are pasting a part of it. save the response to a file and attach it to your question. you may want to save it with .svg extension and try open it with your browser firstSoheil Armin

2 Answers

0
votes

Assuming that the QByteArray is valid (svg xml descriptor coherent and complete, encoding handled correctly), this is working:

QString QS = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
             "<svg version=\"1.1\" viewBox=\"0 0 500 500\" width=\"500px\" height=\"500px\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
             "<title>Test</title>"
             "<rect x=\"100\" y=\"100\" width=\"100\" height=\"100\" stroke=\"blue\" fill=\"purple\" fill-opacity=\"0.5\" stroke-opacity=\"0.8\"/>"
             "</svg>";
QByteArray panelData(QS.toStdString().c_str(), QS.length());
QSvgRenderer renderSVG(panelData);
QImage image(500, 500, QImage::Format_ARGB32_Premultiplied);
QPainter painter(&image);
renderSVG.render(&painter);
bool res = image.save("D:\\HD\\Desktop\\svg.png");
0
votes

After a number of tests, I discovered the problem originated with the encoding. QSvgRenderer does not have the ability to decode the server response directly, which was causing renderSVG.load() to fail. I had to use QTextDocument's decoding function to decode the resposne in such a way where QSvgRenderer can read it.

QString QS = QString::fromUtf8(serverReply.c_str());
QTextDocument text;
text.setHtml(QS);
QString plain = text.toPlainText();
QByteArray panelData(QByteArray::fromStdString(plain.toStdString()));

QSvgRenderer renderSVG;
renderSVG.load(panelData);
QPixmap pix(RenderSVG.defaultSize());
QPainter pixPainter(&pix);
renderSVG.render(&pixPainter);
ui->pixLabel->setPixmap(pix);