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.