Graphics::drawRect seems to be adding rounded corners

I am drawing a grid and it seems that drawRect is rounding the inner corner for some of the cells. Anyone have any ideas? Here is the code and magnified screen capture. In the screen capture notice the upper two rows appear as expected, and the lower two rows have the rounded inner corner.

void SwatchColorSelector::paint (Graphics& g)
{
    for (auto rowIndex = 0; rowIndex < layoutHeight; ++rowIndex)
        for (auto colIndex = 0; colIndex < layoutWidth; ++colIndex)
        {
            const auto colorIndex = (rowIndex * layoutWidth) + colIndex;
            if (colorIndex < colorValues.size())
            {
                const Rectangle<int> swatchLocation (colIndex * swatchWidth, rowIndex * swatchHeight, swatchWidth, swatchHeight);
                g.setColour (colorValues[colorIndex]);
                g.fillRect (swatchLocation);
                g.setColour ((colorIndex == selectedColorIndex) ? Colours::white : CueGray);
                g.drawRect (swatchLocation, 1);
            }
        }
}

Hmm… Normally there is drawRoundedRectangle() for this purpose. Which version of JUCE are you using?

I am using the the develop branch with the latest commit being the 3/13.

Could you provide a complete minimal example (as a PIP if you want) so we can try reproducing?
On which platform are you seeing this?

I’ll put together a minimal app. It looks like it is only happening on Windows, of which I only have an up to date v10 to test with.

Not seeing this here, tested on 10.0.17134. Can you try this PIP and see if it the issue is there for you?

/*******************************************************************************
 The block below describes the properties of this PIP. A PIP is a short snippet
 of code that can be read by the Projucer and used to generate a JUCE project.

 BEGIN_JUCE_PIP_METADATA

  name:             RoundRectangleTest

  dependencies:     juce_core, juce_data_structures, juce_events, juce_graphics, juce_gui_basics
  exporters:        linux_make, vs2017, xcode_mac

  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1

  type:             Component
  mainClass:        MyComponent

 END_JUCE_PIP_METADATA

*******************************************************************************/

#pragma once


//==============================================================================
class MyComponent   : public Component
{
public:
    //==============================================================================
    MyComponent()
    {
        setSize (1000, 1000);
    }

    ~MyComponent()
    {
    }

    //==============================================================================
    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));
    
        static Array<Colour> colours { Colours::red, Colours::green, Colours::blue, Colours::hotpink, Colours::black };
        
        auto b = getLocalBounds();
        auto width = b.getWidth() / 5;
        
        for (int i = 0; i < 5; ++i)
        {
            auto slice = b.removeFromLeft (width);
            
            for (int s = 0; s < 5; ++s)
            {
                g.setColour (colours[i]);
                g.fillRect (slice.removeFromTop (width).reduced (5));
            }
        }
    }

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


private:
    //==============================================================================
    // Your private member variables go here...


    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyComponent)
};


You PIP doesn’t produce the results, but this one does. It seems like it might somehow be related to the color… very odd

/*******************************************************************************
 The block below describes the properties of this PIP. A PIP is a short snippet
 of code that can be read by the Projucer and used to generate a JUCE project.

 BEGIN_JUCE_PIP_METADATA

  name:             RoundRectangleTest

  dependencies:     juce_core, juce_data_structures, juce_events, juce_graphics, juce_gui_basics
  exporters:        linux_make, vs2017, xcode_mac

  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1

  type:             Component
  mainClass:        MyComponent

 END_JUCE_PIP_METADATA

*******************************************************************************/

#pragma once


//==============================================================================
class MyComponent   : public Component
{
public:
    //==============================================================================
    MyComponent()
    {
        setSize (1000, 1000);
    }

    ~MyComponent()
    {
    }

    //==============================================================================
    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));
    

        const auto gridWidth = 10;
        const auto gridHeight = 6;
        const auto numColours = (gridWidth * gridHeight) - 4;
        const auto colourStep = 1.0f / (float)numColours;
        std::vector<Colour> colours;
        for (auto colourIndex = 0; colourIndex < numColours; ++colourIndex)
            colours.push_back (Colour (colourStep * (float)colourIndex, 1.0f, 1.0f, 1.0f));
        colours.push_back (Colour (0x00, 0x00, 0x00));
        colours.push_back (Colour (0x00, 0x00, 0x00));
        colours.push_back (Colour (0xFF, 0xFF, 0xFF));
        colours.push_back (Colour (0xFF, 0xFF, 0xFF));

        const auto cellWidth = getWidth () / gridWidth;
        const auto cellHeight = getHeight () / gridHeight;

        auto b = getLocalBounds();
        auto width = b.getWidth() / gridWidth;
        
        for (int i = 0; i < gridHeight; ++i)
        {
            auto slice = b.removeFromTop (width);
            
            for (int s = 0; s < gridWidth; ++s)
            {
                const auto colorIndex = (i * gridWidth) + s;
                const auto cell = slice.removeFromLeft (width);
                g.setColour (colours[colorIndex]);
                g.fillRect (cell);
                g.setColour (Colours::grey);
                g.drawRect (cell);
            }
        }
    }

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


private:
    //==============================================================================
    // Your private member variables go here...


    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyComponent)
};

Looks fine to me?

If you use the windows zoom tool you can see it…
image

That’s definitely some sort of OS-level interpolating going on there, I can just barely see some sort of rounding if I zoom in on my laptop to 1100% but it’s not at all noticeable at a normal level. There’s nothing we can do in JUCE to change this - even zooming in on the Windows cursor shows some rounded edges on the pointy bits.

1 Like

That was the top of my list of expected reasons! Thanks for checking into it. :slight_smile:

You can turn that smoothing off in the settings for the zoom tool.

1 Like