Search code examples
c++cairogtkmmgtkmm3

How to create std::map of Gdk::Pixbuf instances and use it in Gdk::Cairo


I guess one may found it trivial, but I ask it here since I could not find a straightforward answer.

Let's dive into the problem:

Having a resource of multiple images along with cairo context that is using these images incessantly. Naturally, I can do so as below:

Glib::RefPtr<Gdk::Pixbuf>  image;
image = Gdk::Pixbuf::create_from_resource("/image/icon1"); //there are numerous icons out there

Then I can use it with Cairo context pointer like this:

bool MyClass::on_draw(const Cairo::RefPtr<Cairo::Context> &cr)
{
 // ... some code
 Gdk::Cairo::set_source_pixbuf(cr, image, x0 , y0); //x0 , y0 : somewhere in the context
 cr->paint();
 return true;
}

Images are not changing but it creates Pixbuf instance everytime. I want to use c++ map and put my icons in it. Then, I want to get the image pointer from the map. I did something like this:

std::map<Glib::ustring , GdkPixbuf*> map_Images;
// ..
map_images.insert(pair<Glib::ustring , GdkPixbuf* >("icon1" , image->gobj() )); // I do the same with all of my frequently referred icons

Now, I don't know how should I call this map to use with Cairo context. In other words, how should I make a Glib::RefPtr from the base object, say GdkPixbuf*


Solution

  • I would recommend you to make map_Images a map of type std::map<Glib::ustring , Glib::RefPtr<Gdk::Pixbuf> > and make it data member of MyClass. Because Glib::RefPtr will deallocate the owning object once all references are lost to that pointer.

    What I want to say is that if you have code similar to this:

    ... some function, say fun1 
    {
        Glib::RefPtr<Gdk::Pixbuf>  image;
        image = Gdk::Pixbuf::create_from_resource("/image/icon1");
    
        map_images.insert(pair<Glib::ustring , GdkPixbuf* >("icon1" , image->gobj() ));
    } // image object will die here. So, Gdk::Pixbuf held by Glib::RefPtr will be deallocated
    

    Now, If you will try to access Gdk::Pixbuf * from the map, you will get dangling pointer.

    If that is the case, skip the part that follows. Otherwise, continue reading.

    Creating Glib::RefPtr of type Gdk::Pixbuf seems to be simple. As per source code that I found on GitHub: https://github.com/GNOME/glibmm/blob/master/glib/glibmm/refptr.h, make_refptr_for_instance(T_CppObject* object) API should do the job for you.

    If you really want to create Glib::RefPtr of type Gdk::Pixbuf, you may get it by calling:

    Glib::RefPtr<Gdk::Pixbuf> imageForIcon1 = make_refptr_for_instance<Gdk::Pixbuf>(map_images["icon1"]); // assumption: map_images already has an element with key "icon1"
    

    Hope it helps.