AffineTransform::scale blurry edges

Hi all,

to rescale the components in my application window, I followed roughly the Tutorial on Android screen sizes.
Manage Android screen sizes

Sometimes, when using AffineTransform::scale on a component, the edges get blurry.

Is there a way to avoid that?

Here is an example code with a simple rectangle:

class SimpleRectanlge: public Component {

public:
SimpleRectanlge() {

    setSize(215, 108);
}
~SimpleRectanlge() {}

void paint (Graphics& g) override {
    
    g.fillAll(Colours::yellowgreen);
    
}
void resized() override {
    
}

private:

};

class MainComponent : public Component

{

public :

//==============================================================================

MainComponent();

~MainComponent();

//==============================================================================

void paint (Graphics&) override ;

void resized() override ;

private :

SimpleRectanlge rect;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)

};

MainComponent::MainComponent()

{

addAndMakeVisible(rect);

setSize(600, 300);

}

MainComponent::~MainComponent()

{

}

//==============================================================================

void MainComponent::paint (Graphics& g)

{

// (Our component is opaque, so we must completely fill the background with a solid colour)

g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));

}

void MainComponent::resized()

{

auto rectArea = getLocalBounds().removeFromBottom(50).reduced(10);

rect.setBounds(rectArea);

rect.setTransform(juce::AffineTransform::scale(0.73, 0.73));

rect.setCentrePosition(rectArea.getCentre());

}

1 Like

Components in JUCE can have a sub-pixel position/size when transformed meaning their position and or size may not always be exact integers.

In the example you gave, you’re calculating a juce::Rectangle<int> object with the first line, setting the Component’s bounds, and then scaling the Component which results in a non-integer size.
You could simply scale the rectangle before setting it as the Component’s bounds:

void MainComponent::resized()
{
    auto rectArea = getLocalBounds().removeFromBottom(50).reduced(10).toFloat();
    rectArea = rectArea.transformedBy(juce::AffineTransform::scale(0.73f, 0.73f));
    rect.setBounds(rectArea.toNearestIntEdges());
    rect.setCentrePosition(rectArea.getCentre().roundToInt());
}

If I know I’m going to be using floats somewhere in my layout, I usually find it best to use floats from the start and to only convert to an integer at the very last step.

Thanks ImJimmi!

that solved the problem.

Obviously I’ll now have to change a lot of ints to floats in my Component/SubComponent hierarchy and all the drawing…
I did the exact opposite by doing roundToIntAccurate()on every float before creating my Rectangle<int> objects.

What a pain… :roll_eyes: