PAGE_INFO: use double instead of int to store the page size.

For historical reasons, they are stored in mils, but using int create rounding
issues when converting to/from mils to IU in dialogs.
This is a minor but annoying issue.
Fixes #16000
https://gitlab.com/kicad/code/kicad/-/issues/16000
This commit is contained in:
jean-pierre charras 2023-10-31 13:04:46 +01:00
parent 19ca7cedaa
commit d8be69c3c1
7 changed files with 90 additions and 82 deletions

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2021-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -75,7 +75,7 @@ static const wxString pageFmts[] =
};
DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, double aIuPerMils,
const VECTOR2I& aMaxUserSizeMils ) :
const VECTOR2D& aMaxUserSizeMils ) :
DIALOG_PAGES_SETTINGS_BASE( aParent ),
m_parent( aParent ),
m_screen( m_parent->GetScreen() ),
@ -151,13 +151,13 @@ bool DIALOG_PAGES_SETTINGS::TransferDataToWindow()
if( m_customFmt )
{
m_customSizeX.SetValue( m_pageInfo.GetWidthMils() * m_iuPerMils );
m_customSizeY.SetValue( m_pageInfo.GetHeightMils() * m_iuPerMils );
m_customSizeX.SetDoubleValue( m_pageInfo.GetWidthMils() * m_iuPerMils );
m_customSizeY.SetDoubleValue( m_pageInfo.GetHeightMils() * m_iuPerMils );
}
else
{
m_customSizeX.SetValue( m_pageInfo.GetCustomWidthMils() * m_iuPerMils );
m_customSizeY.SetValue( m_pageInfo.GetCustomHeightMils() * m_iuPerMils );
m_customSizeX.SetDoubleValue( m_pageInfo.GetCustomWidthMils() * m_iuPerMils );
m_customSizeY.SetDoubleValue( m_pageInfo.GetCustomHeightMils() * m_iuPerMils );
}
m_TextRevision->SetValue( m_tb.GetRevision() );
@ -592,8 +592,8 @@ void DIALOG_PAGES_SETTINGS::UpdateDrawingSheetExample()
{
int lyWidth, lyHeight;
wxSize clamped_layout_size( Clamp( MIN_PAGE_SIZE_MILS, m_layout_size.x, m_maxPageSizeMils.x ),
Clamp( MIN_PAGE_SIZE_MILS, m_layout_size.y, m_maxPageSizeMils.y ) );
VECTOR2D clamped_layout_size( Clamp( (double)MIN_PAGE_SIZE_MILS, m_layout_size.x, m_maxPageSizeMils.x ),
Clamp( (double)MIN_PAGE_SIZE_MILS, m_layout_size.y, m_maxPageSizeMils.y ) );
double lyRatio = clamped_layout_size.x < clamped_layout_size.y ?
(double) clamped_layout_size.y / clamped_layout_size.x :
@ -744,8 +744,8 @@ void DIALOG_PAGES_SETTINGS::GetPageLayoutInfoFromDialog()
wxASSERT( i != arrayDim(papers) ); // dialog UI match the above list?
VECTOR2I sz = pageInfo.GetSizeMils();
m_layout_size = VECTOR2I( sz.x, sz.y );
VECTOR2D sz = pageInfo.GetSizeMils();
m_layout_size = VECTOR2D( sz.x, sz.y );
// swap sizes to match orientation
bool isPortrait = (bool) m_orientationComboBox->GetSelection();
@ -761,13 +761,13 @@ void DIALOG_PAGES_SETTINGS::GetPageLayoutInfoFromDialog()
void DIALOG_PAGES_SETTINGS::GetCustomSizeMilsFromDialog()
{
double customSizeX = (double) m_customSizeX.GetValue() / m_iuPerMils;
double customSizeY = (double) m_customSizeY.GetValue() / m_iuPerMils;
double customSizeX = (double) m_customSizeX.GetDoubleValue() / m_iuPerMils;
double customSizeY = (double) m_customSizeY.GetDoubleValue() / m_iuPerMils;
// Prepare to painless double -> int conversion.
// Ensure layout size can be converted to int coordinates later
customSizeX = Clamp( double( INT_MIN ), customSizeX, double( INT_MAX ) );
customSizeY = Clamp( double( INT_MIN ), customSizeY, double( INT_MAX ) );
m_layout_size = VECTOR2I( KiROUND( customSizeX ), KiROUND( customSizeY ) );
m_layout_size = VECTOR2D( customSizeX, customSizeY );
}

View File

@ -65,7 +65,7 @@ const wxChar PAGE_INFO::Custom[] = wxT( "User" );
// also see: wx/defs.h
// local readability macro for millimeter wxSize
#define MMsize( x, y ) VECTOR2I( EDA_UNIT_UTILS::Mm2mils( x ), EDA_UNIT_UTILS::Mm2mils( y ) )
#define MMsize( x, y ) VECTOR2D( EDA_UNIT_UTILS::Mm2mils( x ), EDA_UNIT_UTILS::Mm2mils( y ) )
// All MUST be defined as landscape.
const PAGE_INFO PAGE_INFO::pageA5( MMsize( 210, 148 ), wxT( "A5" ), wxPAPER_A5 );
@ -75,24 +75,24 @@ const PAGE_INFO PAGE_INFO::pageA2( MMsize( 594, 420 ), wxT( "A2" ),
const PAGE_INFO PAGE_INFO::pageA1( MMsize( 841, 594 ), wxT( "A1" ), PAPER_A1 );
const PAGE_INFO PAGE_INFO::pageA0( MMsize( 1189, 841 ), wxT( "A0" ), PAPER_A0 );
const PAGE_INFO PAGE_INFO::pageA( VECTOR2I( 11000, 8500 ), wxT( "A" ), wxPAPER_LETTER );
const PAGE_INFO PAGE_INFO::pageB( VECTOR2I( 17000, 11000 ), wxT( "B" ), wxPAPER_TABLOID );
const PAGE_INFO PAGE_INFO::pageC( VECTOR2I( 22000, 17000 ), wxT( "C" ), wxPAPER_CSHEET );
const PAGE_INFO PAGE_INFO::pageD( VECTOR2I( 34000, 22000 ), wxT( "D" ), wxPAPER_DSHEET );
const PAGE_INFO PAGE_INFO::pageE( VECTOR2I( 44000, 34000 ), wxT( "E" ), wxPAPER_ESHEET );
const PAGE_INFO PAGE_INFO::pageA( VECTOR2D( 11000, 8500 ), wxT( "A" ), wxPAPER_LETTER );
const PAGE_INFO PAGE_INFO::pageB( VECTOR2D( 17000, 11000 ), wxT( "B" ), wxPAPER_TABLOID );
const PAGE_INFO PAGE_INFO::pageC( VECTOR2D( 22000, 17000 ), wxT( "C" ), wxPAPER_CSHEET );
const PAGE_INFO PAGE_INFO::pageD( VECTOR2D( 34000, 22000 ), wxT( "D" ), wxPAPER_DSHEET );
const PAGE_INFO PAGE_INFO::pageE( VECTOR2D( 44000, 34000 ), wxT( "E" ), wxPAPER_ESHEET );
const PAGE_INFO PAGE_INFO::pageGERBER( VECTOR2I( 32000, 32000 ), wxT( "GERBER" ), wxPAPER_NONE );
const PAGE_INFO PAGE_INFO::pageUser( VECTOR2I( 17000, 11000 ), Custom, wxPAPER_NONE );
const PAGE_INFO PAGE_INFO::pageGERBER( VECTOR2D( 32000, 32000 ), wxT( "GERBER" ), wxPAPER_NONE );
const PAGE_INFO PAGE_INFO::pageUser( VECTOR2D( 17000, 11000 ), Custom, wxPAPER_NONE );
// US paper sizes
const PAGE_INFO PAGE_INFO::pageUSLetter( VECTOR2I( 11000, 8500 ), wxT( "USLetter" ), wxPAPER_LETTER );
const PAGE_INFO PAGE_INFO::pageUSLegal( VECTOR2I( 14000, 8500 ), wxT( "USLegal" ), wxPAPER_LEGAL );
const PAGE_INFO PAGE_INFO::pageUSLedger( VECTOR2I( 17000, 11000 ), wxT( "USLedger" ),
const PAGE_INFO PAGE_INFO::pageUSLetter( VECTOR2D( 11000, 8500 ), wxT( "USLetter" ), wxPAPER_LETTER );
const PAGE_INFO PAGE_INFO::pageUSLegal( VECTOR2D( 14000, 8500 ), wxT( "USLegal" ), wxPAPER_LEGAL );
const PAGE_INFO PAGE_INFO::pageUSLedger( VECTOR2D( 17000, 11000 ), wxT( "USLedger" ),
wxPAPER_TABLOID );
// Custom paper size for next instantiation of type "User"
int PAGE_INFO::s_user_width = 17000;
int PAGE_INFO::s_user_height = 11000;
double PAGE_INFO::s_user_width = 17000;
double PAGE_INFO::s_user_height = 11000;
inline void PAGE_INFO::updatePortrait()
@ -102,7 +102,7 @@ inline void PAGE_INFO::updatePortrait()
}
PAGE_INFO::PAGE_INFO( const VECTOR2I& aSizeMils, const wxString& aType, wxPaperSize aPaperId ) :
PAGE_INFO::PAGE_INFO( const VECTOR2D& aSizeMils, const wxString& aType, wxPaperSize aPaperId ) :
m_type( aType ), m_size( aSizeMils ), m_paper_id( aPaperId )
{
updatePortrait();
@ -200,7 +200,7 @@ void PAGE_INFO::SetPortrait( bool aIsPortrait )
}
static int clampWidth( int aWidthInMils )
static double clampWidth( double aWidthInMils )
{
/* was giving EESCHEMA single component SVG plotter grief
However a minimal test is made to avoid values that crashes Kicad
@ -215,7 +215,7 @@ static int clampWidth( int aWidthInMils )
}
static int clampHeight( int aHeightInMils )
static double clampHeight( double aHeightInMils )
{
/* was giving EESCHEMA single component SVG plotter grief
clamping is best done at the UI, i.e. dialog, levels
@ -225,25 +225,26 @@ static int clampHeight( int aHeightInMils )
else if( aHeightInMils > 44000 )
aHeightInMils = 44000;
*/
if( aHeightInMils < 10 )
aHeightInMils = 10;
if( aHeightInMils < 10.0 )
aHeightInMils = 10.0;
return aHeightInMils;
}
void PAGE_INFO::SetCustomWidthMils( int aWidthInMils )
void PAGE_INFO::SetCustomWidthMils( double aWidthInMils )
{
s_user_width = clampWidth( aWidthInMils );
}
void PAGE_INFO::SetCustomHeightMils( int aHeightInMils )
void PAGE_INFO::SetCustomHeightMils( double aHeightInMils )
{
s_user_height = clampHeight( aHeightInMils );
}
void PAGE_INFO::SetWidthMils( int aWidthInMils )
void PAGE_INFO::SetWidthMils( double aWidthInMils )
{
if( m_size.x != aWidthInMils )
{
@ -257,7 +258,7 @@ void PAGE_INFO::SetWidthMils( int aWidthInMils )
}
void PAGE_INFO::SetHeightMils( int aHeightInMils )
void PAGE_INFO::SetHeightMils( double aHeightInMils )
{
if( m_size.y != aHeightInMils )
{

View File

@ -1838,23 +1838,23 @@ void SCH_SEXPR_PARSER::parsePAGE_INFO( PAGE_INFO& aPageInfo )
if( pageType == PAGE_INFO::Custom )
{
int width = EDA_UNIT_UTILS::Mm2mils( parseDouble( "width" ) ); // width stored in mm so we convert to mils
int width = parseDouble( "width" );
// Perform some controls to avoid crashes if the size is edited by hands
if( width < MIN_PAGE_SIZE_MILS )
width = MIN_PAGE_SIZE_MILS;
else if( width > MAX_PAGE_SIZE_EESCHEMA_MILS )
width = MAX_PAGE_SIZE_EESCHEMA_MILS;
if( width < MIN_PAGE_SIZE_MM )
width = MIN_PAGE_SIZE_MM;
else if( width > MAX_PAGE_SIZE_EESCHEMA_MM )
width = MAX_PAGE_SIZE_EESCHEMA_MM;
int height = EDA_UNIT_UTILS::Mm2mils( parseDouble( "height" ) ); // height stored in mm so we convert to mils
int height = parseDouble( "height" );
if( height < MIN_PAGE_SIZE_MILS )
height = MIN_PAGE_SIZE_MILS;
else if( height > MAX_PAGE_SIZE_EESCHEMA_MILS )
height = MAX_PAGE_SIZE_EESCHEMA_MILS;
if( height < MIN_PAGE_SIZE_MM )
height = MIN_PAGE_SIZE_MM;
else if( height > MAX_PAGE_SIZE_EESCHEMA_MM )
height = MAX_PAGE_SIZE_EESCHEMA_MM;
aPageInfo.SetWidthMils( width );
aPageInfo.SetHeightMils( height );
aPageInfo.SetWidthMM( width );
aPageInfo.SetHeightMM( height );
}
token = NextTok();

View File

@ -1505,8 +1505,8 @@ void SCH_LEGACY_PLUGIN::Format( SCH_SHEET* aSheet )
const PAGE_INFO& page = screen->GetPageSettings();
m_out->Print( 0, "$Descr %s %d %d%s\n", TO_UTF8( page.GetType() ),
page.GetWidthMils(),
page.GetHeightMils(),
(int)page.GetWidthMils(),
(int)page.GetHeightMils(),
!page.IsCustom() && page.IsPortrait() ? " portrait" : "" );
m_out->Print( 0, "encoding utf-8\n" );
m_out->Print( 0, "Sheet %d %d\n", screen->GetVirtualPageNumber(), screen->GetPageCount() );

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -36,7 +36,7 @@ class DIALOG_PAGES_SETTINGS: public DIALOG_PAGES_SETTINGS_BASE
{
public:
DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, double aIuPerMils,
const VECTOR2I& aMaxUserSizeMils );
const VECTOR2D& aMaxUserSizeMils );
virtual ~DIALOG_PAGES_SETTINGS();
const wxString GetWksFileName()
@ -121,8 +121,8 @@ protected:
bool m_initialized;
bool m_localPrjConfigChanged; /// the page layuout filename was changed
wxBitmap* m_pageBitmap; /// Temporary bitmap for the drawing sheet example.
VECTOR2I m_layout_size; /// Logical drawing sheet size.
VECTOR2I m_maxPageSizeMils; /// The max page size allowed by the caller frame
VECTOR2D m_layout_size; /// Logical drawing sheet size.
VECTOR2D m_maxPageSizeMils; /// The max page size allowed by the caller frame
PAGE_INFO m_pageInfo; /// Temporary page info.
bool m_customFmt; /// true if the page selection is custom
TITLE_BLOCK m_tb; /// Temporary title block (basic inscriptions).

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2007-2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2008-2013 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2007-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2007-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -38,6 +38,11 @@
#define MAX_PAGE_SIZE_PCBNEW_MILS 48000
#define MAX_PAGE_SIZE_EESCHEMA_MILS 120000
/// Min and max page sizes for clamping, in mm.
#define MIN_PAGE_SIZE_MM 25.4
#define MAX_PAGE_SIZE_PCBNEW_MM 48000*.0254
#define MAX_PAGE_SIZE_EESCHEMA_MM 120000*.0254
class OUTPUTFORMATTER;
/**
@ -125,13 +130,17 @@ public:
*/
wxPaperSize GetPaperId() const { return m_paper_id; }
void SetWidthMils( int aWidthInMils );
int GetWidthMils() const { return m_size.x; }
void SetWidthMM( double aWidthInMM ) { SetWidthMils( aWidthInMM * 1000 / 25.4 ); }
void SetWidthMils( double aWidthInMils );
double GetWidthMils() const { return m_size.x; }
double GetWidthMM() const { return m_size.x * 25.4 / 1000; }
void SetHeightMils( int aHeightInMils );
int GetHeightMils() const { return m_size.y; }
void SetHeightMM( double aHeightInMM ) { SetHeightMils( aHeightInMM * 1000 / 25.4 ); }
void SetHeightMils( double aHeightInMils );
double GetHeightMils() const { return m_size.y; }
double GetHeightMM() const { return m_size.y * 25.4 / 1000; }
const VECTOR2I& GetSizeMils() const { return m_size; }
const VECTOR2D& GetSizeMils() const { return m_size; }
/**
* Gets the page width in IU
@ -158,32 +167,32 @@ public:
* variable being passed. Note, this constexpr variable changes depending
* on application, hence why it is passed.
*/
const VECTOR2I GetSizeIU( double aIUScale ) const
const VECTOR2D GetSizeIU( double aIUScale ) const
{
return VECTOR2I( GetWidthIU( aIUScale ), GetHeightIU( aIUScale ) );
return VECTOR2D( GetWidthIU( aIUScale ), GetHeightIU( aIUScale ) );
}
/**
* Set the width of Custom page in mils for any custom page constructed or made via
* SetType() after making this call.
*/
static void SetCustomWidthMils( int aWidthInMils );
static void SetCustomWidthMils( double aWidthInMils );
/**
* Set the height of Custom page in mils for any custom page constructed or made via
* SetType() after making this call.
*/
static void SetCustomHeightMils( int aHeightInMils );
static void SetCustomHeightMils( double aHeightInMils );
/**
* @return custom paper width in mils.
*/
static int GetCustomWidthMils() { return s_user_width; }
static double GetCustomWidthMils() { return s_user_width; }
/**
* @return custom paper height in mils.
*/
static int GetCustomHeightMils() { return s_user_height; }
static double GetCustomHeightMils() { return s_user_height; }
/**
* Output the page class to \a aFormatter in s-expression form.
@ -197,7 +206,7 @@ public:
protected:
// only the class implementation(s) may use this constructor
PAGE_INFO( const VECTOR2I& aSizeMils, const wxString& aName, wxPaperSize aPaperId );
PAGE_INFO( const VECTOR2D& aSizeMils, const wxString& aName, wxPaperSize aPaperId );
private:
// standard pre-defined sizes
@ -223,14 +232,14 @@ private:
// all dimensions here are in mils
wxString m_type; ///< paper type: A4, A3, etc.
VECTOR2I m_size; ///< mils
VECTOR2D m_size; ///< mils
bool m_portrait; ///< true if portrait, false if landscape
wxPaperSize m_paper_id; ///< wx' style paper id.
static int s_user_height;
static int s_user_width;
static double s_user_height;
static double s_user_width;
void updatePortrait();

View File

@ -1283,23 +1283,21 @@ void PCB_PARSER::parsePAGE_INFO()
{
double width = parseDouble( "width" ); // width in mm
const double Mils2mm = 0.0254;
// Perform some controls to avoid crashes if the size is edited by hands
if( width < MIN_PAGE_SIZE_MILS*Mils2mm )
width = MIN_PAGE_SIZE_MILS*Mils2mm;
else if( width > MAX_PAGE_SIZE_PCBNEW_MILS*Mils2mm )
width = MAX_PAGE_SIZE_PCBNEW_MILS*Mils2mm;
if( width < MIN_PAGE_SIZE_MM )
width = MIN_PAGE_SIZE_MM;
else if( width > MAX_PAGE_SIZE_PCBNEW_MM )
width = MAX_PAGE_SIZE_PCBNEW_MM;
double height = parseDouble( "height" ); // height in mm
if( height < MIN_PAGE_SIZE_MILS*Mils2mm )
height = MIN_PAGE_SIZE_MILS*Mils2mm;
else if( height > MAX_PAGE_SIZE_PCBNEW_MILS*Mils2mm )
height = MAX_PAGE_SIZE_PCBNEW_MILS*Mils2mm;
if( height < MIN_PAGE_SIZE_MM )
height = MIN_PAGE_SIZE_MM;
else if( height > MAX_PAGE_SIZE_PCBNEW_MM )
height = MAX_PAGE_SIZE_PCBNEW_MM;
pageInfo.SetWidthMils( EDA_UNIT_UTILS::Mm2mils( width ) );
pageInfo.SetHeightMils( EDA_UNIT_UTILS::Mm2mils( height ) );
pageInfo.SetWidthMM( width );
pageInfo.SetHeightMM( height );
}
token = NextTok();