SVG && fast update
I'm developing an application that show an SVG image with some circles that must change the fill opacity on some event.
Actually, to change the opacity, every time I do:
load the file in a QByteArray svgArray
replace "fill-opacity:1" with "fill-opacity:0" for the object I must change
re-call widget::paintEvent by calling update():
The problem is that in this way the application always reload all svg also if the change is very small and the operation is too slow.
The slowest part is:
but if I don't call load() function the change doesn't happens.
What can I do to speed up the application?
How about caching the resulting bitmap images? Getting them onto the screen is way faster than rerendering SVG all the time!
The memory overhead of caching should not be too large if it is really only these the states you need to save.
the SVG image is not so big and I only must update some state by changing the fill-opacity.
How do I update a portion of the bitmap when a state change happens?
This is not so clear for me...
It does not really matter how big the change in the SVG is: You end up rerendering the complete SVG image. Rendering SVG is always much slower than just putting a pixmap onto the screen.
Of course you can just cache the area that changes and paste it over the effected area... Just construct a QPixmap of the area by copying it out of the original one and then use the QPainter APIs to paint it to wherever needed.
The problem now is that I need a way to automatically find the region that change without knowing it before.
I don't know witch SVG will be charged by user.
Can't you just use the QPainter architecture to draw circles rather than using SVG at all?
[quote author="Jorj" date="1277798615"]Can't you just use the QPainter architecture to draw circles rather than using SVG at all?[/quote]
No, because user of the application must be able to open his own SVG.
The application must be able to change the state of the element it find in the new SVG.
Is it possible it would be faster to load using the XML stream option, then you can keep the XML heirachy in memory, change the tag you want, and reload the xml?
However, I think the cache to pixmap is better option...
Qt may benefit from the ability to load an SVG to something like a QPicture, but editable, then you could navigate the heirachy in code not via byte arrays. That would give better performance...
Thanks for answer...
[quote author="Jorj" date="1277971476"]Is it possible it would be faster to load using the XML stream option, then you can keep the XML heirachy in memory, change the tag you want, and reload the xml?
This is what I do but, after changing the tag I want, actually I call:
svgArray = svgXml.toByteArray();
The slowest line is:
[quote author="Jorj" date="1277971476"]
Qt may benefit from the ability to load an SVG to something like a QPicture, but editable, then you could navigate the heirachy in code not via byte arrays. That would give better performance…
I don't understand this solution very well...
To load the svg to a QPicture is possible but how do I change some tag without reloading the svg to the same QPicture...?
You may get better performance from load if you miss out the toByteArray step... using the QXmlStreamReader construction or load option...
but actually... QXmlStreamReader isn't what i thought it was, only an xml reader, you can't edit it... what you need to be able to do (i dont know if its possible) is to pass the svg renderer the QDomDocument you have containing your svg.
My second solution was more of a pointer to the Qt Trolls, it would be useful if QPicture (or a similar class) had vector editing type functions, but it doesn't, so it wont solve your problem.
My vote is still with bitmap caching, but vector editing - if possible, is cooler.
So I think there is no solution...
A way to speed up would be to update only a part of the svg (the part witch has the tag I changed) but I think it's not possible.
I found a possible solution but I don't know how to use it...
The solution consist in using QSvgRenderer::boundsOnElement .
It seems that it's possible to render only a part of the svg identified by the Id.
The step should be:
render the svg in a QImage
update the element in the original svg
render the changed part (with boundsOnElement) in the same QImage
Now I must study how to put the changed element in the same place of the background image to cover the old element.