SVG Image Best Practices

I’m a beginner (at everything!) trying to use an SVG as a background image. I did it this first way before I started using the debugger. Now that I do, an exception is thrown for memory leaking when closing the window:

Drawable* background_image = Drawable::createFromImageData (BinaryData::bg_svg, BinaryData::bg_svgSize);
background_image->setBounds (getLocalBounds());
addAndMakeVisible (background_image);

Searching through the forums showed me I should be using ScopedPointers instead of regular pointers. This doesn’t throw an exception, but also doesn’t display:

ScopedPointer<Drawable> background_image (Drawable::createFromImageData (BinaryData::bg_svg, BinaryData::bg_svgSize));
background_image->setBounds (getLocalBounds());
addAndMakeVisible (background_image);

This next one works, but the tooltip says, “Note that the preferred way to render a drawable in future is by using it as a component and adding it to a parent, so you might want to consider that before using this method.”, so I’m a bit wary to use it:

ScopedPointer<Drawable> background_image = Drawable::createFromImageData (BinaryData::bg_svg, BinaryData::bg_svgSize);
background_image->draw(g, 1.f, AffineTransform()); 

I wouldn’t be surprised if there’s a way to do this without pointers, and maybe is the right way that I just don’t know about. I’ve also used a PNG file in the same manner as the first method, so I hope that learning how to best do this will give me a clue on how to handle that problem as well. Any help will be greatly appreciated!

The suggested way is to make the scoped pointer a member of your component class, call createFromImageData in the constructor and add it as a child component. You should be doing the first step anyway, creating a new Drawable every time the component repaints is excessive.

I wouldn’t be super wary of that message in the documentation. If they deprecate that method then it would be impossible to use SVG graphics with the LookAndFeel classes.

As far as I know, that’s how I’ve been trying to get it to work. I have ScopedPointer<Drawable> background_image; in the header, with this in the constructor(the 2nd one from the first post):

ScopedPointer<Drawable> background_image (Drawable::createFromImageData (BinaryData::bg_svg, BinaryData::bg_svgSize));
background_image->setBounds (getLocalBounds());
addAndMakeVisible (background_image);

but it’s still blank. I’ve tried a brand new GUI application, with nothing but the above added, to no avail.

The one that goes into the the paint() member function is the only one of the three that doesn’t leak and shows the image.

With the third version, I tried having only background_image->draw(g, 1.f, AffineTransform()); in paint(), but it crashes on start up then. But yeah, creating a Drawable over and over like that doesn’t sound right either.

I think the one in this post will work eventually, once I figure out what the missing piece is. Thanks for the response! I should probably stop for the day; 6 hours of banging my head against this means I should pick this up tomorrow :face_with_head_bandage:

Your ‘ScopedPointer background_image’ declaration in your constructor overrides your member variable declaration with a local variable of the same name (ie. you need to learn more about ‘scope’), and I believe the bounds are 0,0 in the constructor.

1 Like

I’ve tried it with and without ScopedPointer<Drawable> background_image; in the header (but thank you for adding to my checklist.txt of things I should watch out for: overriding things when I don’t mean to). The one that uses Drawable* background_image and displays-but-leaks lets me setBounds() with getLocalBounds() or 0, 0, 530, 400 (the image size), so that doesn’t seem like a problem. My uninformed common sense thinks that replacing Drawable* with ScopedPointer<Drawable> should have worked, since I did that with a bunch of drawableButtons and it worked fine.

The post you’re replying to is pointing out that you’re not initializing the class member because you’ve put ScopedPointer <Drawable> in front of the variable name in your constructor, which declares a local variable and overrides the name of the class member.

Ohhh, well that cleared it up enough to get me on the right track:

//in the header:
ScopedPointer<Drawable> background_image;

//in the constructor:
background_image = Drawable::createFromImageData (BinaryData::bg_svg, BinaryData::bg_svgSize);
addAndMakeVisible (background_image);
background_image->setBounds (getLocalBounds());

Thank you guys for pointing me in the right direction! :smiley:

2 Likes