Svg image is drawn with unexpected additional parts


#1

Hi,

I want to use a svg image as a background to my application. A colleague created a quick sketch of a background with inkspace that looks like this:

This is added as binary data through the projucer. Various viewers including the small preview version of the image shown in the projucer display it correctly. However, when it gets drawn in a JUCE component some additional lines and other stuff, my colleague obviously used to create the image but made invisible before exporting it as svg appear so that it looks like this:

(Please ignore the sliders… :wink:)

It gets simply drawn like that:

// private member of the component containing it
ScopedPointer<Drawable> background = Drawable::createFromImageData(BinaryData::ALL_Example_svg, BinaryData::ALL_Example_svgSize);

// ... 

// this is called in "paint"
Rectangle<float> windowArea (0, 0, getWidth(), getHeight());
background->drawWithin(g, windowArea, RectanglePlacement::centred, 1.0);

So, what’s wrong here? Why does JUCE draw stuff other editors don’t show? How could this be fixed?

Thank you & have a nice Sunday!


#2

Hi,

this is still an open question for me. I had another thought while looking at the preview of this file in the Projucer Window. There it looks perfectly as it should - no characters and pink lines as seen in the screenshot above:

All stuff that was set invisible before exporting (the text and pink lines) does not appear in this view. So I looked into the projucers source code and found the ItemPreviewComponent which I suspect to be the piece of code that manages drawing this preview image. I tried to find out what is done differently here, did not really find a clue and started copying the drawing part line by line to find out if at any point the invisible lines suddenly disappear. After that I switched to loading the image from the original file at runtime instead of taking it from the binary data, just as the ItemPreviewComponent does - with no success too. In the end I got an image with the same size as the version in the preview section of the projucer but with all invisible parts visible.

Now, I create the drawable like this:

ScopedPointer<XmlElement> svg (XmlDocument::parse (file));

if (svg != nullptr)
    drawable = Drawable::createFromSVG (*svg);

with “file” and “drawable” being private members of the component class and “file” set to the absolute path of the image.

And this is my paint method:

Rectangle<float> contentBounds (background->getDrawableBounds());
Rectangle<float> area = RectanglePlacement (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize)
.appliedTo (contentBounds, Rectangle<float> (4.0f, 22.0f, getWidth() - 8.0f, getHeight() - 26.0f));

drawable->draw (g, 1.0f, RectanglePlacement (RectanglePlacement::stretchToFit)
                .getTransformToFit (contentBounds, area.toFloat()));

Any ideas on that? It would be really helpful!


#3

Are you perhaps drawing it multiple times inside a bunch of components, so that the pink lines are just the background colour leaking through the sub-pixel gaps between these components?


#4

No, I don’t think so. I talked to my colleague who created this image, these pink lines and the text around it are items, he created and used in inkspace while building up the image. He just set them invisible before exporting.

Just to be sure, I created a fresh, empty JUCE Audio application, copied the ItemPreviewComponent from the projucer source to my project and added a single ItemPreviewComponent to display my svg file. The code looks like that:

#include "../JuceLibraryCode/JuceHeader.h"
#include "ItemPreviewComponent.h"

//==============================================================================
/*
This component lives inside our window, and this is where you should put all
your controls and content.
*/
class MainContentComponent   : public AudioAppComponent
{
public:
    //==============================================================================
MainContentComponent() : file("/Volumes/Daten/Benutzerordner/Entwicklung/DSP_Mate/GUI/DSP-App/Graphic/ALL_Example.svg")
{
    setSize (800, 600);

    // specify the number of input and output channels that we want to open
    setAudioChannels (2, 2);
    
    svgPreview = new ItemPreviewComponent(file);
    
    addAndMakeVisible(svgPreview);
    svgPreview->setBounds(0, 0, getHeight(), getWidth());

}

~MainContentComponent()
{
    shutdownAudio();
}

// ... all the usual audio stuff here

// did not touch this part
void paint (Graphics& g) override
{
    // (Our component is opaque, so we must completely fill the background with a solid colour)
    g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
    // You can add your drawing code here!
}

void resized() override
{
    // This is called when the MainContentComponent is resized.
    // If you add any child components, this is where you should
    // update their positions.
}


private:
//==============================================================================

// Your private member variables go here...
File file;
ScopedPointer<ItemPreviewComponent> svgPreview;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};


// (This function is called by the app startup code to create our main component)
Component* createMainContentComponent()     { return new MainContentComponent(); }

Sadly, the result looks like that:

Is there any magic happening to the file inside the projucer, before passing it to the ItemPreviewComponent?


#5

Nope. Maybe just the different size is making them visible? Are you definitely using the latest juce version from the tip of develop? There were some SVG fixes recently.


#6

:flushed:

No. I was using v5.0.1 from the master branch. Just updated my juce submodule to use the tip of the development branch and all works & looks as expected. I just didn’t expect that there were such recent changes to the svg part…

Thanks for your patience in answering anyway, jules!