You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
8.9 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2023 KiCad Developers, see AUTHORS.TXT for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include <common.h>
  25. #include <page_info.h>
  26. #include <macros.h>
  27. #include <eda_units.h>
  28. // late arriving wxPAPER_A0, wxPAPER_A1
  29. #if wxABI_VERSION >= 20999
  30. #define PAPER_A0 wxPAPER_A0
  31. #define PAPER_A1 wxPAPER_A1
  32. #else
  33. #define PAPER_A0 wxPAPER_A2
  34. #define PAPER_A1 wxPAPER_A2
  35. #endif
  36. // Standard paper sizes nicknames.
  37. const wxChar PAGE_INFO::A5[] = wxT( "A5" );
  38. const wxChar PAGE_INFO::A4[] = wxT( "A4" );
  39. const wxChar PAGE_INFO::A3[] = wxT( "A3" );
  40. const wxChar PAGE_INFO::A2[] = wxT( "A2" );
  41. const wxChar PAGE_INFO::A1[] = wxT( "A1" );
  42. const wxChar PAGE_INFO::A0[] = wxT( "A0" );
  43. const wxChar PAGE_INFO::A[] = wxT( "A" );
  44. const wxChar PAGE_INFO::B[] = wxT( "B" );
  45. const wxChar PAGE_INFO::C[] = wxT( "C" );
  46. const wxChar PAGE_INFO::D[] = wxT( "D" );
  47. const wxChar PAGE_INFO::E[] = wxT( "E" );
  48. const wxChar PAGE_INFO::GERBER[] = wxT( "GERBER" );
  49. const wxChar PAGE_INFO::USLetter[] = wxT( "USLetter" );
  50. const wxChar PAGE_INFO::USLegal[] = wxT( "USLegal" );
  51. const wxChar PAGE_INFO::USLedger[] = wxT( "USLedger" );
  52. const wxChar PAGE_INFO::Custom[] = wxT( "User" );
  53. // Standard page sizes in mils, all constants
  54. // see: https://lists.launchpad.net/kicad-developers/msg07389.html
  55. // also see: wx/defs.h
  56. // local readability macro for millimeter wxSize
  57. #define MMsize( x, y ) VECTOR2I( EDA_UNIT_UTILS::Mm2mils( x ), EDA_UNIT_UTILS::Mm2mils( y ) )
  58. // All MUST be defined as landscape.
  59. const PAGE_INFO PAGE_INFO::pageA5( MMsize( 210, 148 ), wxT( "A5" ), wxPAPER_A5 );
  60. const PAGE_INFO PAGE_INFO::pageA4( MMsize( 297, 210 ), wxT( "A4" ), wxPAPER_A4 );
  61. const PAGE_INFO PAGE_INFO::pageA3( MMsize( 420, 297 ), wxT( "A3" ), wxPAPER_A3 );
  62. const PAGE_INFO PAGE_INFO::pageA2( MMsize( 594, 420 ), wxT( "A2" ), wxPAPER_A2 );
  63. const PAGE_INFO PAGE_INFO::pageA1( MMsize( 841, 594 ), wxT( "A1" ), PAPER_A1 );
  64. const PAGE_INFO PAGE_INFO::pageA0( MMsize( 1189, 841 ), wxT( "A0" ), PAPER_A0 );
  65. const PAGE_INFO PAGE_INFO::pageA( VECTOR2I( 11000, 8500 ), wxT( "A" ), wxPAPER_LETTER );
  66. const PAGE_INFO PAGE_INFO::pageB( VECTOR2I( 17000, 11000 ), wxT( "B" ), wxPAPER_TABLOID );
  67. const PAGE_INFO PAGE_INFO::pageC( VECTOR2I( 22000, 17000 ), wxT( "C" ), wxPAPER_CSHEET );
  68. const PAGE_INFO PAGE_INFO::pageD( VECTOR2I( 34000, 22000 ), wxT( "D" ), wxPAPER_DSHEET );
  69. const PAGE_INFO PAGE_INFO::pageE( VECTOR2I( 44000, 34000 ), wxT( "E" ), wxPAPER_ESHEET );
  70. const PAGE_INFO PAGE_INFO::pageGERBER( VECTOR2I( 32000, 32000 ), wxT( "GERBER" ), wxPAPER_NONE );
  71. const PAGE_INFO PAGE_INFO::pageUser( VECTOR2I( 17000, 11000 ), Custom, wxPAPER_NONE );
  72. // US paper sizes
  73. const PAGE_INFO PAGE_INFO::pageUSLetter( VECTOR2I( 11000, 8500 ), wxT( "USLetter" ), wxPAPER_LETTER );
  74. const PAGE_INFO PAGE_INFO::pageUSLegal( VECTOR2I( 14000, 8500 ), wxT( "USLegal" ), wxPAPER_LEGAL );
  75. const PAGE_INFO PAGE_INFO::pageUSLedger( VECTOR2I( 17000, 11000 ), wxT( "USLedger" ),
  76. wxPAPER_TABLOID );
  77. // Custom paper size for next instantiation of type "User"
  78. int PAGE_INFO::s_user_width = 17000;
  79. int PAGE_INFO::s_user_height = 11000;
  80. inline void PAGE_INFO::updatePortrait()
  81. {
  82. // update m_portrait based on orientation of m_size.x and m_size.y
  83. m_portrait = ( m_size.y > m_size.x );
  84. }
  85. PAGE_INFO::PAGE_INFO( const VECTOR2I& aSizeMils, const wxString& aType, wxPaperSize aPaperId ) :
  86. m_type( aType ), m_size( aSizeMils ), m_paper_id( aPaperId )
  87. {
  88. updatePortrait();
  89. // This constructor is protected, and only used by const PAGE_INFO's known
  90. // only to class implementation, so no further changes to "this" object are
  91. // expected.
  92. }
  93. PAGE_INFO::PAGE_INFO( const wxString& aType, bool aIsPortrait )
  94. {
  95. SetType( aType, aIsPortrait );
  96. }
  97. bool PAGE_INFO::SetType( const wxString& aType, bool aIsPortrait )
  98. {
  99. bool rc = true;
  100. // all are landscape initially
  101. if( aType == pageA5.GetType() )
  102. *this = pageA5;
  103. else if( aType == pageA4.GetType() )
  104. *this = pageA4;
  105. else if( aType == pageA3.GetType() )
  106. *this = pageA3;
  107. else if( aType == pageA2.GetType() )
  108. *this = pageA2;
  109. else if( aType == pageA1.GetType() )
  110. *this = pageA1;
  111. else if( aType == pageA0.GetType() )
  112. *this = pageA0;
  113. else if( aType == pageA.GetType() )
  114. *this = pageA;
  115. else if( aType == pageB.GetType() )
  116. *this = pageB;
  117. else if( aType == pageC.GetType() )
  118. *this = pageC;
  119. else if( aType == pageD.GetType() )
  120. *this = pageD;
  121. else if( aType == pageE.GetType() )
  122. *this = pageE;
  123. else if( aType == pageGERBER.GetType() )
  124. *this = pageGERBER;
  125. else if( aType == pageUSLetter.GetType() )
  126. *this = pageUSLetter;
  127. else if( aType == pageUSLegal.GetType() )
  128. *this = pageUSLegal;
  129. else if( aType == pageUSLedger.GetType() )
  130. *this = pageUSLedger;
  131. else if( aType == pageUser.GetType() )
  132. {
  133. // pageUser is const, and may not and does not hold the custom size,
  134. // so customize *this later
  135. *this = pageUser;
  136. // customize:
  137. m_size.x = s_user_width;
  138. m_size.y = s_user_height;
  139. updatePortrait();
  140. }
  141. else
  142. rc = false;
  143. if( aIsPortrait )
  144. {
  145. // all private PAGE_INFOs are landscape, must swap x and y
  146. std::swap( m_size.y, m_size.x );
  147. updatePortrait();
  148. }
  149. return rc;
  150. }
  151. bool PAGE_INFO::IsCustom() const
  152. {
  153. return m_type == Custom;
  154. }
  155. void PAGE_INFO::SetPortrait( bool aIsPortrait )
  156. {
  157. if( m_portrait != aIsPortrait )
  158. {
  159. // swap x and y in m_size
  160. std::swap( m_size.y, m_size.x );
  161. m_portrait = aIsPortrait;
  162. // margins are not touched, do that if you want
  163. }
  164. }
  165. static int clampWidth( int aWidthInMils )
  166. {
  167. /* was giving EESCHEMA single component SVG plotter grief
  168. However a minimal test is made to avoid values that crashes Kicad
  169. if( aWidthInMils < 4000 ) // 4" is about a baseball card
  170. aWidthInMils = 4000;
  171. else if( aWidthInMils > 44000 ) //44" is plotter size
  172. aWidthInMils = 44000;
  173. */
  174. if( aWidthInMils < 10 )
  175. aWidthInMils = 10;
  176. return aWidthInMils;
  177. }
  178. static int clampHeight( int aHeightInMils )
  179. {
  180. /* was giving EESCHEMA single component SVG plotter grief
  181. clamping is best done at the UI, i.e. dialog, levels
  182. However a minimal test is made to avoid values that crashes Kicad
  183. if( aHeightInMils < 4000 )
  184. aHeightInMils = 4000;
  185. else if( aHeightInMils > 44000 )
  186. aHeightInMils = 44000;
  187. */
  188. if( aHeightInMils < 10 )
  189. aHeightInMils = 10;
  190. return aHeightInMils;
  191. }
  192. void PAGE_INFO::SetCustomWidthMils( int aWidthInMils )
  193. {
  194. s_user_width = clampWidth( aWidthInMils );
  195. }
  196. void PAGE_INFO::SetCustomHeightMils( int aHeightInMils )
  197. {
  198. s_user_height = clampHeight( aHeightInMils );
  199. }
  200. void PAGE_INFO::SetWidthMils( int aWidthInMils )
  201. {
  202. if( m_size.x != aWidthInMils )
  203. {
  204. m_size.x = clampWidth( aWidthInMils );
  205. m_type = Custom;
  206. m_paper_id = wxPAPER_NONE;
  207. updatePortrait();
  208. }
  209. }
  210. void PAGE_INFO::SetHeightMils( int aHeightInMils )
  211. {
  212. if( m_size.y != aHeightInMils )
  213. {
  214. m_size.y = clampHeight( aHeightInMils );
  215. m_type = Custom;
  216. m_paper_id = wxPAPER_NONE;
  217. updatePortrait();
  218. }
  219. }
  220. void PAGE_INFO::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
  221. {
  222. aFormatter->Print( aNestLevel, "(paper %s", aFormatter->Quotew( GetType() ).c_str() );
  223. // The page dimensions are only required for user defined page sizes.
  224. // Internally, the page size is in mils
  225. if( GetType() == PAGE_INFO::Custom )
  226. aFormatter->Print( 0, " %g %g",
  227. GetWidthMils() * 25.4 / 1000.0,
  228. GetHeightMils() * 25.4 / 1000.0 );
  229. if( !IsCustom() && IsPortrait() )
  230. aFormatter->Print( 0, " portrait" );
  231. aFormatter->Print( 0, ")\n" );
  232. }