Hi all,
I’ve noticed that adjacent SVG elements become slightly misaligned when they are resized or scaled. It seems like this is to do with floating point truncation or rounding but I can’t find where this is occurring.
Below is a simple example application that adds 3 copies of an SVG containing 4 adjacent squares to a window. The first copy resizes trivially, the second sets a transform and the 3rd sets a transform and puts the component in a Viewport. On resizing, you can see in each copy of the svg the black squares go in and out of alignment and the copy within the Viewport also comes away at the edges. I have attached a screenshot to show the application window after resizing – you can see that the black squares are misaligned and the 3rd copy has also come away at its left edge. Before resizing everything is perfectly aligned.
Can anyone propose a solution to this? Or even just shed any light on what exactly is going on here?
Thanks,
George
After resizing:
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
static const char* gapTestSVG = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<svg version=\"1.1\" id=\"GapTest\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\""
"width=\"333px\" height=\"110px\" viewBox=\"0 0 333 110\" style=\"enable-background:new 0 0 333 110;\" xml:space=\"preserve\">"
"<rect x=\"20\" y=\"20\" style=\"fill:#1A1A1A;\" width=\"30\" height=\"30\"/>"
"<rect x=\"50\" y=\"50\" style=\"fill:#1A1A1A;\" width=\"30\" height=\"30\"/>"
"<rect x=\"20\" y=\"50\" style=\"fill:#1A1A1A;\" width=\"30\" height=\"30\"/>"
"<rect x=\"50\" y=\"20\" style=\"fill:#1A1A1A;\" width=\"30\" height=\"30\"/>"
"<rect x=\"10\" y=\"10\" style=\"fill:none;stroke:#FF0000;stroke-miterlimit:10;\" width=\"80\" height=\"80\"/>"
"</svg>";
class Holder : public Component
{
public:
Holder()
: svg (Drawable::createFromImageData (gapTestSVG, String (gapTestSVG).getNumBytesAsUTF8()))
{
setBounds (svg->getDrawableBounds().withZeroOrigin().getSmallestIntegerContainer());
}
void paint (Graphics& g) override
{
g.fillAll (Colour (0xffffffff));
svg->drawWithin (g, getLocalBounds().toFloat(), RectanglePlacement::centred, 1.0f);
}
private:
ScopedPointer<Drawable> svg;
};
//==============================================================================
class MainContentComponent : public Component
{
public:
MainContentComponent()
{
addAndMakeVisible (holderResized);
addAndMakeVisible (holderTransformed);
viewport.setViewedComponent (&holderTransformedScrollable, false);
addAndMakeVisible (viewport);
setSize (1200, 400);
}
void resized() override
{
auto areaReamining = getLocalBounds();
holderResized.setBounds (areaReamining.removeFromLeft (areaReamining.getWidth() / 3));
auto xform = RectanglePlacement (RectanglePlacement::centred)
.getTransformToFit (holderTransformed.getBounds().toFloat(),
areaReamining.removeFromLeft (areaReamining.getWidth() / 2).toFloat());
holderTransformed.setTransform (xform);
auto xformScrollable = RectanglePlacement (RectanglePlacement::centred)
.getTransformToFit (holderTransformedScrollable.getBounds().toFloat(),
areaReamining.toFloat());
holderTransformedScrollable.setTransform (xformScrollable);
viewport.setBounds (areaReamining);
}
void mouseDown (const MouseEvent& e) override
{
holderResized.repaint();
holderTransformed.repaint();
}
private:
Holder holderResized;
Holder holderTransformed;
Holder holderTransformedScrollable;
Viewport viewport;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};