SHAPE_RECT: add Normalize method to assure width or height > 0

ROUNDRECT: add option to normalize the rectangle on creation

if the created rectangle has a negative size(width or height) there are issues
when drawing it.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21613
Fixes https://gitlab.com/kicad/code/kicad/-/issues/21610
This commit is contained in:
jean-pierre charras 2025-09-01 11:54:48 +02:00
parent 5fb55ccb30
commit 5b31b11731
6 changed files with 46 additions and 6 deletions

View File

@ -1592,10 +1592,12 @@ void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer, bool aDimmed )
case SHAPE_T::RECTANGLE:
if( shape->GetCornerRadius() > 0 )
{
// Creates a normalized ROUNDRECT item
// (GetRectangleWidth() and GetRectangleHeight() can be < 0 with transforms
ROUNDRECT rr( SHAPE_RECT( shape->GetPosition(),
shape->GetRectangleWidth(),
shape->GetRectangleHeight() ),
shape->GetCornerRadius() );
shape->GetCornerRadius(), true /* normalize */ );
SHAPE_POLY_SET poly;
rr.TransformToPolygon( poly );
m_gal->DrawPolygon( poly );

View File

@ -37,7 +37,15 @@ class ROUNDRECT
public:
ROUNDRECT() : m_rect(), m_radius( 0 ) {}
ROUNDRECT( SHAPE_RECT aRect, int aRadius );
/**
* Creates a ROUNDRECT instance
* @param aRect in the rectangle model
* @param aRadius is the radius of the round rect
* @param aNormalizeOnCreate allows normalization of the created rect, i.e ensure
* width and height > 0, regardless width and height of aRect
* allowing normalization can modifiy the value of origin of created instance from aRect
*/
ROUNDRECT( SHAPE_RECT aRect, int aRadius, bool aNormalizeOnCreate = false );
static ROUNDRECT OutsetFrom( const SHAPE_RECT& aRect, int aOutset );

View File

@ -238,6 +238,12 @@ public:
void TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError,
ERROR_LOC aErrorLoc ) const override;
/**
* Ensure that the height and width are positive.
*/
void Normalize();
private:
VECTOR2I m_p0; ///< Top-left corner
int m_w; ///< Width

View File

@ -48,13 +48,18 @@ SHAPE_ARC MakeSideArcCw180( const SHAPE_RECT& aRect, int aRadius, DIRECTION_45::
} // namespace
ROUNDRECT::ROUNDRECT( SHAPE_RECT aRect, int aRadius ) :
ROUNDRECT::ROUNDRECT( SHAPE_RECT aRect, int aRadius, bool aNormalizeOnCreate ) :
m_rect( std::move( aRect ) ),
m_radius( aRadius )
{
if( aNormalizeOnCreate )
m_rect.Normalize();
// Ensure radius is compatible with rectangle size:
if( m_radius > m_rect.MinorDimension()/2 )
m_radius = m_rect.MinorDimension()/2;
int min_radius = std::abs( m_rect.MinorDimension() )/2;
if( m_radius > min_radius )
m_radius = min_radius;
if( m_radius < 0 )
m_radius = 0;

View File

@ -162,3 +162,20 @@ const SHAPE_LINE_CHAIN SHAPE_RECT::Outline() const
rv.SetClosed( true );
return rv;
}
void SHAPE_RECT::Normalize()
{
// Ensure that the height and width are positive.
if( m_w < 0 )
{
m_w = -m_w;
m_p0.x -= m_w;
}
if( m_h < 0 )
{
m_h = -m_h;
m_p0.y -= m_h;
}
}

View File

@ -1977,9 +1977,11 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
{
if( aShape->GetCornerRadius() > 0 )
{
// Creates a normalized ROUNDRECT item
// (GetRectangleWidth() and GetRectangleHeight() can be < 0 with transforms
ROUNDRECT rr( SHAPE_RECT( aShape->GetStart(), aShape->GetRectangleWidth(),
aShape->GetRectangleHeight() ),
aShape->GetCornerRadius() );
aShape->GetCornerRadius(), true /* normalize */ );
SHAPE_POLY_SET poly;
rr.TransformToPolygon( poly );
SHAPE_LINE_CHAIN outline = poly.Outline( 0 );