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) 2012 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 
25 
26 #include <common.h>
27 #include <page_info.h>
28 #include <macros.h>
29 
30 
31 // late arriving wxPAPER_A0, wxPAPER_A1
32 #if wxABI_VERSION >= 20999
33  #define PAPER_A0   wxPAPER_A0
34  #define PAPER_A1   wxPAPER_A1
35 #else
36  #define PAPER_A0   wxPAPER_A2
37  #define PAPER_A1   wxPAPER_A2
38 #endif
39 
40 
41 // Standard paper sizes nicknames.
42 const wxChar PAGE_INFO::A5[] = wxT( "A5" );
43 const wxChar PAGE_INFO::A4[] = wxT( "A4" );
44 const wxChar PAGE_INFO::A3[] = wxT( "A3" );
45 const wxChar PAGE_INFO::A2[] = wxT( "A2" );
46 const wxChar PAGE_INFO::A1[] = wxT( "A1" );
47 const wxChar PAGE_INFO::A0[] = wxT( "A0" );
48 const wxChar PAGE_INFO::A[]  = wxT( "A" );
49 const wxChar PAGE_INFO::B[]  = wxT( "B" );
50 const wxChar PAGE_INFO::C[]  = wxT( "C" );
51 const wxChar PAGE_INFO::D[]  = wxT( "D" );
52 const wxChar PAGE_INFO::E[]  = wxT( "E" );
53 
54 const wxChar PAGE_INFO::GERBER[]   = wxT( "GERBER" );
55 const wxChar PAGE_INFO::USLetter[] = wxT( "USLetter" );
56 const wxChar PAGE_INFO::USLegal[]  = wxT( "USLegal" );
57 const wxChar PAGE_INFO::USLedger[] = wxT( "USLedger" );
58 const wxChar PAGE_INFO::Custom[]   = wxT( "User" );
59 
60 
61 // Standard page sizes in mils, all constants
62 // see:  https://lists.launchpad.net/kicad-developers/msg07389.html
63 // also see: wx/defs.h
64 
65 // local readability macro for millimeter wxSize
66 #define MMsize( x, y )  wxSize( Mm2mils( x ), Mm2mils( y ) )
67 
68 // All MUST be defined as landscape.
69 const PAGE_INFO  PAGE_INFO::pageA5(     MMsize( 210,   148 ),   wxT( "A5" ),    wxPAPER_A5 );
70 const PAGE_INFO  PAGE_INFO::pageA4(     MMsize( 297,   210 ),   wxT( "A4" ),    wxPAPER_A4 );
71 const PAGE_INFO  PAGE_INFO::pageA3(     MMsize( 420,   297 ),   wxT( "A3" ),    wxPAPER_A3 );
72 const PAGE_INFO  PAGE_INFO::pageA2(     MMsize( 594,   420 ),   wxT( "A2" ),    wxPAPER_A2 );
73 const PAGE_INFO  PAGE_INFO::pageA1(     MMsize( 841,   594 ),   wxT( "A1" ),    PAPER_A1 );
74 const PAGE_INFO  PAGE_INFO::pageA0(     MMsize( 1189,  841 ),   wxT( "A0" ),    PAPER_A0 );
75 
76 const PAGE_INFO  PAGE_INFO::pageA(      wxSize( 11000,  8500 ), wxT( "A" ), wxPAPER_LETTER );
77 const PAGE_INFO  PAGE_INFO::pageB(      wxSize( 17000, 11000 ), wxT( "B" ), wxPAPER_TABLOID );
78 const PAGE_INFO  PAGE_INFO::pageC(      wxSize( 22000, 17000 ), wxT( "C" ), wxPAPER_CSHEET );
79 const PAGE_INFO  PAGE_INFO::pageD(      wxSize( 34000, 22000 ), wxT( "D" ), wxPAPER_DSHEET );
80 const PAGE_INFO  PAGE_INFO::pageE(      wxSize( 44000, 34000 ), wxT( "E" ), wxPAPER_ESHEET );
81 
82 const PAGE_INFO  PAGE_INFO::pageGERBER( wxSize( 32000, 32000 ), wxT( "GERBER" ), wxPAPER_NONE  );
83 const PAGE_INFO  PAGE_INFO::pageUser(   wxSize( 17000, 11000 ), Custom,         wxPAPER_NONE );
84 
85 // US paper sizes
86 const PAGE_INFO  PAGE_INFO::pageUSLetter( wxSize( 11000, 8500  ),  wxT( "USLetter" ), wxPAPER_LETTER );
87 const PAGE_INFO  PAGE_INFO::pageUSLegal(  wxSize( 14000, 8500  ),  wxT( "USLegal" ),  wxPAPER_LEGAL );
88 const PAGE_INFO  PAGE_INFO::pageUSLedger( wxSize( 17000, 11000 ),  wxT( "USLedger" ), wxPAPER_TABLOID );
89 
90 // Custom paper size for next instantiation of type "User"
91 int PAGE_INFO::s_user_width  = 17000;
92 int PAGE_INFO::s_user_height = 11000;
93 
94 
updatePortrait()95 inline void PAGE_INFO::updatePortrait()
96 {
97     // update m_portrait based on orientation of m_size.x and m_size.y
98     m_portrait = ( m_size.y > m_size.x );
99 }
100 
101 
PAGE_INFO(const wxSize & aSizeMils,const wxString & aType,wxPaperSize aPaperId)102 PAGE_INFO::PAGE_INFO( const wxSize& aSizeMils, const wxString& aType, wxPaperSize aPaperId ) :
103     m_type( aType ), m_size( aSizeMils ), m_paper_id( aPaperId )
104 {
105     updatePortrait();
106 
107     // This constructor is protected, and only used by const PAGE_INFO's known
108     // only to class implementation, so no further changes to "this" object are
109     // expected.
110 }
111 
112 
PAGE_INFO(const wxString & aType,bool aIsPortrait)113 PAGE_INFO::PAGE_INFO( const wxString& aType, bool aIsPortrait )
114 {
115     SetType( aType, aIsPortrait );
116 }
117 
118 
SetType(const wxString & aType,bool aIsPortrait)119 bool PAGE_INFO::SetType( const wxString& aType, bool aIsPortrait )
120 {
121     bool rc = true;
122 
123     // all are landscape initially
124     if( aType == pageA5.GetType() )
125         *this = pageA5;
126     else if( aType == pageA4.GetType() )
127         *this = pageA4;
128     else if( aType == pageA3.GetType() )
129         *this = pageA3;
130     else if( aType == pageA2.GetType() )
131         *this = pageA2;
132     else if( aType == pageA1.GetType() )
133         *this = pageA1;
134     else if( aType == pageA0.GetType() )
135         *this = pageA0;
136     else if( aType == pageA.GetType() )
137         *this = pageA;
138     else if( aType == pageB.GetType() )
139         *this = pageB;
140     else if( aType == pageC.GetType() )
141         *this = pageC;
142     else if( aType == pageD.GetType() )
143         *this = pageD;
144     else if( aType == pageE.GetType() )
145         *this = pageE;
146     else if( aType == pageGERBER.GetType() )
147         *this = pageGERBER;
148     else if( aType == pageUSLetter.GetType() )
149         *this = pageUSLetter;
150     else if( aType == pageUSLegal.GetType() )
151         *this = pageUSLegal;
152     else if( aType == pageUSLedger.GetType() )
153         *this = pageUSLedger;
154     else if( aType == pageUser.GetType() )
155     {
156         // pageUser is const, and may not and does not hold the custom size,
157         // so customize *this later
158         *this  = pageUser;
159 
160         // customize:
161         m_size.x = s_user_width;
162         m_size.y = s_user_height;
163 
164         updatePortrait();
165     }
166     else
167         rc = false;
168 
169     if( aIsPortrait )
170     {
171         // all private PAGE_INFOs are landscape, must swap x and y
172         m_size = wxSize( m_size.y, m_size.x );
173         updatePortrait();
174     }
175 
176     return rc;
177 }
178 
179 
IsCustom() const180 bool PAGE_INFO::IsCustom() const
181 {
182     return m_type == Custom;
183 }
184 
185 
SetPortrait(bool aIsPortrait)186 void PAGE_INFO::SetPortrait( bool aIsPortrait )
187 {
188     if( m_portrait != aIsPortrait )
189     {
190         // swap x and y in m_size
191         m_size = wxSize( m_size.y, m_size.x );
192 
193         m_portrait = aIsPortrait;
194 
195         // margins are not touched, do that if you want
196     }
197 }
198 
199 
clampWidth(int aWidthInMils)200 static int clampWidth( int aWidthInMils )
201 {
202 /*  was giving EESCHEMA single component SVG plotter grief
203     However a minimal test is made to avoid values that crashes Kicad
204     if( aWidthInMils < 4000 )       // 4" is about a baseball card
205         aWidthInMils = 4000;
206     else if( aWidthInMils > 44000 ) //44" is plotter size
207         aWidthInMils = 44000;
208 */
209     if( aWidthInMils < 10 )
210         aWidthInMils = 10;
211     return aWidthInMils;
212 }
213 
214 
clampHeight(int aHeightInMils)215 static int clampHeight( int aHeightInMils )
216 {
217 /*  was giving EESCHEMA single component SVG plotter grief
218     clamping is best done at the UI, i.e. dialog, levels
219     However a minimal test is made to avoid values that crashes Kicad
220     if( aHeightInMils < 4000 )
221         aHeightInMils = 4000;
222     else if( aHeightInMils > 44000 )
223         aHeightInMils = 44000;
224 */
225     if( aHeightInMils < 10 )
226         aHeightInMils = 10;
227     return aHeightInMils;
228 }
229 
230 
SetCustomWidthMils(int aWidthInMils)231 void PAGE_INFO::SetCustomWidthMils( int aWidthInMils )
232 {
233     s_user_width = clampWidth( aWidthInMils );
234 }
235 
236 
SetCustomHeightMils(int aHeightInMils)237 void PAGE_INFO::SetCustomHeightMils( int aHeightInMils )
238 {
239     s_user_height = clampHeight( aHeightInMils );
240 }
241 
242 
SetWidthMils(int aWidthInMils)243 void PAGE_INFO::SetWidthMils(  int aWidthInMils )
244 {
245     if( m_size.x != aWidthInMils )
246     {
247         m_size.x = clampWidth( aWidthInMils );
248 
249         m_type = Custom;
250         m_paper_id = wxPAPER_NONE;
251 
252         updatePortrait();
253     }
254 }
255 
256 
SetHeightMils(int aHeightInMils)257 void PAGE_INFO::SetHeightMils( int aHeightInMils )
258 {
259     if( m_size.y != aHeightInMils )
260     {
261         m_size.y = clampHeight( aHeightInMils );
262 
263         m_type = Custom;
264         m_paper_id = wxPAPER_NONE;
265 
266         updatePortrait();
267     }
268 }
269 
270 
Format(OUTPUTFORMATTER * aFormatter,int aNestLevel,int aControlBits) const271 void PAGE_INFO::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
272 {
273     aFormatter->Print( aNestLevel, "(paper %s", aFormatter->Quotew( GetType() ).c_str() );
274 
275     // The page dimensions are only required for user defined page sizes.
276     // Internally, the page size is in mils
277     if( GetType() == PAGE_INFO::Custom )
278         aFormatter->Print( 0, " %g %g",
279                            GetWidthMils() * 25.4 / 1000.0,
280                            GetHeightMils() * 25.4 / 1000.0 );
281 
282     if( !IsCustom() && IsPortrait() )
283         aFormatter->Print( 0, " portrait" );
284 
285     aFormatter->Print( 0, ")\n" );
286 }
287