diff --git a/common/gr_text.cpp b/common/gr_text.cpp index 0e5dcd075e..2a2a71149a 100644 --- a/common/gr_text.cpp +++ b/common/gr_text.cpp @@ -41,7 +41,7 @@ int GetPenSizeForBold( int aTextSize ) int GetPenSizeForDemiBold( int aTextSize ) { - return KiROUND( aTextSize / 6 ); + return KiROUND( aTextSize / 6.0 ); } diff --git a/eeschema/dialogs/panel_setup_pinmap.cpp b/eeschema/dialogs/panel_setup_pinmap.cpp index eaa696d397..85f0d97e9e 100644 --- a/eeschema/dialogs/panel_setup_pinmap.cpp +++ b/eeschema/dialogs/panel_setup_pinmap.cpp @@ -174,11 +174,11 @@ void PANEL_SETUP_PINMAP::reBuildMatrixPanel() if( ( ii == jj ) && !m_initialized ) { - wxPoint textPos( x + KiROUND( bitmapSize.x / 2 ), + wxPoint textPos( x + KiROUND( bitmapSize.x / 2.0 ), y - charSize.y * 2 ); new wxStaticText( m_matrixPanel, wxID_ANY, CommentERC_V[ii], textPos ); - wxPoint calloutPos( x + KiROUND( bitmapSize.x / 2 ), + wxPoint calloutPos( x + KiROUND( bitmapSize.x / 2.0 ), y - charSize.y ); new wxStaticText( m_matrixPanel, wxID_ANY, "|", calloutPos ); } diff --git a/eeschema/sch_io/eagle/sch_io_eagle.cpp b/eeschema/sch_io/eagle/sch_io_eagle.cpp index fedf145103..2c1b4219b6 100644 --- a/eeschema/sch_io/eagle/sch_io_eagle.cpp +++ b/eeschema/sch_io/eagle/sch_io_eagle.cpp @@ -1653,7 +1653,7 @@ SCH_TEXT* SCH_IO_EAGLE::loadLabel( const std::unique_ptr& aLabel, if( aLabel->rot ) { - for( int i = 0; i < KiROUND( aLabel->rot->degrees / 90 ) %4; ++i ) + for( int i = 0; i < KiROUND( aLabel->rot->degrees / 90.0 ) %4; ++i ) label->Rotate90( false ); if( aLabel->rot->mirror ) diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp index 1bae9ed4f7..7ff702cb39 100644 --- a/eeschema/sch_painter.cpp +++ b/eeschema/sch_painter.cpp @@ -558,7 +558,7 @@ int SCH_PAINTER::getOperatingPointTextSize() const int screenTextSize = std::abs( (int) m_gal->GetScreenWorldMatrix().GetScale().y * 7 ); // 66% zoom-relative - return KiROUND( ( docTextSize + screenTextSize * 2 ) / 3 ); + return KiROUND( ( docTextSize + screenTextSize * 2 ) / 3.0 ); } @@ -1272,7 +1272,7 @@ void SCH_PAINTER::drawAnchor( const VECTOR2I& aPos, bool aDrawingShadows ) // In order for the anchors to be visible but unobtrusive, their size must factor in the // current zoom level. const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix(); - int radius = KiROUND( std::fabs( matrix.GetScale().x * TEXT_ANCHOR_SIZE ) / 25 ) + int radius = KiROUND( std::fabs( matrix.GetScale().x * TEXT_ANCHOR_SIZE ) / 25.0 ) + schIUScale.MilsToIU( TEXT_ANCHOR_SIZE ); COLOR4D color = aDrawingShadows ? m_schSettings.GetLayerColor( LAYER_SELECTION_SHADOWS ) diff --git a/eeschema/tools/sch_selection_tool.cpp b/eeschema/tools/sch_selection_tool.cpp index 3575846be0..3f37268901 100644 --- a/eeschema/tools/sch_selection_tool.cpp +++ b/eeschema/tools/sch_selection_tool.cpp @@ -1317,7 +1317,7 @@ bool SCH_SELECTION_TOOL::CollectHits( SCH_COLLECTOR& aCollector, const VECTOR2I& const std::vector& aScanTypes ) { int pixelThreshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) ); - int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() / 2 ); + int gridThreshold = KiROUND( getView()->GetGAL()->GetGridSize().EuclideanNorm() / 2.0 ); aCollector.m_Threshold = std::max( pixelThreshold, gridThreshold ); aCollector.m_ShowPinElectricalTypes = m_frame->GetRenderSettings()->m_ShowPinsElectricalType; diff --git a/include/gr_text.h b/include/gr_text.h index 84251c928d..cb76e21ed2 100644 --- a/include/gr_text.h +++ b/include/gr_text.h @@ -94,7 +94,7 @@ inline void InferBold( TEXT_ATTRIBUTES* aAttrs ) */ inline int GetKnockoutTextMargin( const VECTOR2I& aSize, int aThickness ) { - return std::max( KiROUND( aThickness / 2 ), KiROUND( aSize.y / 9.0 ) ); + return std::max( KiROUND( aThickness / 2.0 ), KiROUND( aSize.y / 9.0 ) ); } diff --git a/libs/kimath/include/math/util.h b/libs/kimath/include/math/util.h index f1812f934a..daaae8ae79 100644 --- a/libs/kimath/include/math/util.h +++ b/libs/kimath/include/math/util.h @@ -40,6 +40,7 @@ #include #include #include +#include /** * Helper to avoid directly including wx/log.h for the templated functions in kimath @@ -92,53 +93,38 @@ inline constexpr ret_type KiCheckedCast( in_type v ) /** - * Round a floating point number to an integer using "round halfway cases away from zero". + * Round a numeric value to an integer using "round halfway cases away from zero" and + * clamp the result to the limits of the return type. * * In Debug build an assert fires if will not fit into the return type. */ template constexpr ret_type KiROUND( fp_type v, bool aQuiet = false ) { - using max_ret = long long int; - fp_type ret = v < 0 ? v - 0.5 : v + 0.5; + using limits = std::numeric_limits; - if( ret > std::numeric_limits::max() ) - { - if( !aQuiet ) - { - kimathLogOverflow( double( v ), typeid( ret_type ).name() ); - } - - return std::numeric_limits::max() - 1; - } - else if( ret < std::numeric_limits::lowest() ) - { - if( !aQuiet ) - { - kimathLogOverflow( double( v ), typeid( ret_type ).name() ); - } - - if( std::numeric_limits::is_signed ) - return std::numeric_limits::lowest() + 1; - else - return 0; - } #if __cplusplus >= 202302L // isnan is not constexpr until C++23 - else if constexpr( std::is_floating_point_v ) + if constexpr( std::is_floating_point_v ) { if( std::isnan( v ) ) { if( !aQuiet ) - { kimathLogOverflow( double( v ), typeid( ret_type ).name() ); - } return 0; } } #endif - return ret_type( max_ret( ret ) ); + long long rounded = std::llround( v ); + long long clamped = std::clamp( rounded, + static_cast( limits::lowest() ), + static_cast( limits::max() ) ); + + if( !aQuiet && clamped != rounded ) + kimathLogOverflow( double( v ), typeid( ret_type ).name() ); + + return static_cast( clamped ); } #ifdef HAVE_WIMPLICIT_FLOAT_CONVERSION diff --git a/pcbnew/connectivity/connectivity_data.cpp b/pcbnew/connectivity/connectivity_data.cpp index 1b9829c327..acef8cdd74 100644 --- a/pcbnew/connectivity/connectivity_data.cpp +++ b/pcbnew/connectivity/connectivity_data.cpp @@ -767,7 +767,7 @@ bool CONNECTIVITY_DATA::TestTrackEndpointDangling( PCB_TRACK* aTrack, bool aIgno // each end. If that's their only connection then they're still dangling. PCB_LAYER_ID layer = aTrack->GetLayer(); - int accuracy = KiROUND( aTrack->GetWidth() / 2 ); + int accuracy = KiROUND( aTrack->GetWidth() / 2.0 ); int start_count = 0; int end_count = 0; diff --git a/pcbnew/connectivity/connectivity_items.cpp b/pcbnew/connectivity/connectivity_items.cpp index 996568fd05..436a833630 100644 --- a/pcbnew/connectivity/connectivity_items.cpp +++ b/pcbnew/connectivity/connectivity_items.cpp @@ -342,9 +342,9 @@ bool CN_ANCHOR::IsDangling() const return connected_count < minimal_count; if( Parent()->Type() == PCB_TRACE_T || Parent()->Type() == PCB_ARC_T ) - accuracy = KiROUND( static_cast( Parent() )->GetWidth() / 2 ); + accuracy = KiROUND( static_cast( Parent() )->GetWidth() / 2.0 ); else if( Parent()->Type() == PCB_SHAPE_T ) - accuracy = KiROUND( static_cast( Parent() )->GetWidth() / 2 ); + accuracy = KiROUND( static_cast( Parent() )->GetWidth() / 2.0 ); // Items with multiple anchors have usually items connected to each anchor. // We want only the item count of this anchor point diff --git a/pcbnew/exporters/export_d356.cpp b/pcbnew/exporters/export_d356.cpp index b934f389e9..560f7effee 100644 --- a/pcbnew/exporters/export_d356.cpp +++ b/pcbnew/exporters/export_d356.cpp @@ -91,7 +91,7 @@ static int compute_pad_access_code( BOARD *aPcb, LSET aLayerMask ) /* Convert and clamp a size from IU to decimils */ static int iu_to_d356(int iu, int clamp) { - int val = KiROUND( iu / ( pcbIUScale.IU_PER_MILS / 10 ) ); + int val = KiROUND( static_cast( iu ) / ( pcbIUScale.IU_PER_MILS / 10.0 ) ); if( val > clamp ) return clamp; if( val < -clamp ) return -clamp; return val; diff --git a/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp b/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp index 17d45526f7..e32f1d1bcf 100644 --- a/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp +++ b/pcbnew/pcb_io/eagle/pcb_io_eagle.cpp @@ -739,7 +739,7 @@ void PCB_IO_EAGLE::loadPlain( wxXmlNode* aGraphics ) pcbtxt->SetText( kicadText ); double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default - int textThickness = KiROUND( t.size.ToPcbUnits() * ratio / 100 ); + int textThickness = KiROUND( t.size.ToPcbUnits() * ratio / 100.0 ); pcbtxt->SetTextThickness( textThickness ); pcbtxt->SetTextSize( kicad_fontsize( t.size, textThickness ) ); pcbtxt->SetKeepUpright( false ); @@ -1033,7 +1033,7 @@ void PCB_IO_EAGLE::loadPlain( wxXmlNode* aGraphics ) if( d.textsize ) { double ratio = 8; // DTD says 8 is default - textThickness = KiROUND( d.textsize->ToPcbUnits() * ratio / 100 ); + textThickness = KiROUND( d.textsize->ToPcbUnits() * ratio / 100.0 ); textSize = kicad_fontsize( *d.textsize, textThickness ); } @@ -1710,7 +1710,7 @@ void PCB_IO_EAGLE::orientFPText( FOOTPRINT* aFootprint, const EELEMENT& e, PCB_T ratio = *a.ratio; VECTOR2I fontz = aFPText->GetTextSize(); - int textThickness = KiROUND( fontz.y * ratio / 100 ); + int textThickness = KiROUND( fontz.y * ratio / 100.0 ); aFPText->SetTextThickness( textThickness ); @@ -2123,7 +2123,7 @@ void PCB_IO_EAGLE::packageText( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const textItem->SetLayer( layer ); double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default - int textThickness = KiROUND( t.size.ToPcbUnits() * ratio / 100 ); + int textThickness = KiROUND( t.size.ToPcbUnits() * ratio / 100.0 ); textItem->SetTextThickness( textThickness ); textItem->SetTextSize( kicad_fontsize( t.size, textThickness ) ); diff --git a/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.h b/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.h index 853e046f7b..e7a5a89059 100644 --- a/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.h +++ b/pcbnew/pcb_io/easyeda/pcb_io_easyeda_parser.h @@ -53,7 +53,7 @@ public: double ScaleSize( double aValue ) override { // - return KiROUND( ( aValue * 254000 ) / 100 ) * 100; + return KiROUND( ( aValue * 254000.0 ) / 100.0 ) * 100; } void ParseBoard( BOARD* aBoard, const VECTOR2D& aOrigin, diff --git a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.h b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.h index 6dbc611d4f..7c291d11d7 100644 --- a/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.h +++ b/pcbnew/pcb_io/easyedapro/pcb_io_easyedapro_parser.h @@ -55,7 +55,7 @@ public: template static T ScaleSize( T aValue ) { - return KiROUND( aValue * 25400 / 500 ) * 500; + return KiROUND( aValue * 25400.0 / 500.0 ) * 500; } template diff --git a/pcbnew/tools/convert_tool.cpp b/pcbnew/tools/convert_tool.cpp index 52211b2403..606daef7b6 100644 --- a/pcbnew/tools/convert_tool.cpp +++ b/pcbnew/tools/convert_tool.cpp @@ -445,7 +445,7 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent ) if( resolvedSettings.m_Strategy == BOUNDING_HULL ) { if( resolvedSettings.m_Gap > 0 ) - resolvedSettings.m_Gap += KiROUND( (double) resolvedSettings.m_LineWidth / 2 ); + resolvedSettings.m_Gap += KiROUND( (double) resolvedSettings.m_LineWidth / 2.0 ); } if( !getPolys( resolvedSettings ) ) diff --git a/qa/tests/pcbnew/test_zone_filler.cpp b/qa/tests/pcbnew/test_zone_filler.cpp index 341f9ac754..43d96c193b 100644 --- a/qa/tests/pcbnew/test_zone_filler.cpp +++ b/qa/tests/pcbnew/test_zone_filler.cpp @@ -46,7 +46,7 @@ struct ZONE_FILL_TEST_FIXTURE }; -constexpr int delta = KiROUND( 0.006 * pcbIUScale.IU_PER_MM ); +int delta = KiROUND( 0.006 * pcbIUScale.IU_PER_MM ); BOOST_FIXTURE_TEST_CASE( BasicZoneFills, ZONE_FILL_TEST_FIXTURE )