Drawing a lot of SVG images is slow
Quentin Cosendey <[email protected]> Tue, 1 Apr 2025 19:36:31 +0200
| Newsgroups | gmane.comp.lib.wxwindows.general |
|---|---|
| Message-ID | <[email protected]> |
Hello,
I'm developing a game. I'm trying to use SVG images to draw the board
and all game elements (tokens, dice, etc.).
I wanted to use SVG because it allows the board to be seen all at once
and have its size adapted to the size of the window, i.e. fill the
window as much as possible / make the board as big as possible, without
pixelization effects. It also allows the user to customize the color of
some game elements (for example tokens) quite easily, as well as select
their own colors to make their own dark or high-contrast mode. All this
is good for visually impaired players.
However, displaying everything (~1000 elements) seems to be quite slow,
and it makes the interface lagging globally. It takes hundreds of
milliseconds to update the screen after having pressed a key and/or
moved the mouse.
Am I doing something wrong ? Do you have ideas on how I could improve
performances ?
Drawing code looks as follows, I have tried to simplify it a little:
void GameWindow::OnPaint (wxPaintEvent& e) {
wxAutoBufferedPaintDC dc(this);
std::unique_ptr<wxGraphicsContext> g(wxGraphicsContext::Create(dc));
...
for (auto& square: squares) {
wxRect pos = ... ; // boundaries of the square
g->ResetClip();
g->Clip(pos);
for (std::string& image: square.getElements()) {
auto bundle = app.getImage(image);
wxSize defaultSize = bundle.GetDefaultSize();
wxSize finalImageSize =
calcGreatestPossibleSize(wxSize(pos.width, pos.height), defaultSize);
auto bitmap = bundle.GetBitmap(finalImageSize);
if (bitmap.IsOk()) {
finalImageSize = bitmap.GetSize();
g->DrawBitmap(bitmap, pos.x, pos.y, finalImageSize.x,
finalImageSize.y);
}
}
g->ResetClip();
}
}
Loading code: wxImageBundle are stored in a
std::unordered_map<std::string, wxImageBundle> .
Using a simple array instead of the map and indexing images by index
instead of by name doesn't make a lot of difference, I have already tested.
wxBitmapBundle App::getImage (const std::string& name) {
auto it = images.find(name);
if (it!=images.end()) return it->second;
wxString svgfn = "images/" + name + ".svg";
if (!svgfn.size()) return wxBitmapBundle(); // not found, return
empty bundle
wxSize imSize = readSVGImageSize(svgfn);
auto bundle = wxBitmapBundle::FromSVGFile(svgfn, imSize);
images[name] = bundle;
return bundle;
}
The SVG images used are extremely simple for the moment, there are no
complex things: basic shapes, polygons, polylines, paths; plain fill and
stroke colors, no gradients or stuff like that.
Most squares have always the same size if the window isn't resized.
In case it can make a difference, GameWindows extends wxControl,
wxVarHVScrollHelper, wxAccessible
Where could the problem be ?
As far as I understand, the method wxImageBundle::GetBitmap basically
renders the SVG in a traditional in-memory bitmap. Is that really
necessary ? Isn't there a more direct way to draw SVG images ?
The documentation says that generated bitmaps are cached, so since the
size don't change unless the window is resized, it shouldn't be a
problem, right ?
Is SVG support in WX just not made for that kind of thing ?
In this case do you have an alternate SVG library integrable with WX to
advise ?
Thank you very much for your answers !
--
Please read https://www.wxwidgets.org/support/mlhowto.htm before posting.
---
You received this message because you are subscribed to the Google Groups "wx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/wx-users/6b90542c-47af-48da-9851-883ece612e48%40bluewin.ch.