2
* @file page_layout_writer.cpp
3
* @brief write an S expression of description of graphic items and texts
4
* to build a title block and page layout
8
* This program source code file is part of KiCad, a free EDA CAD application.
10
* Copyright (C) 1992-2013 Jean-Pierre Charras <jp.charras at wanadoo.fr>.
11
* Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors.
14
* This program is free software; you can redistribute it and/or
15
* modify it under the terms of the GNU General Public License
16
* as published by the Free Software Foundation; either version 2
17
* of the License, or (at your option) any later version.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, you may find one here:
26
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
27
* or you may search the http://www.gnu.org website for the version 2 license,
28
* or you may write to the Free Software Foundation, Inc.,
29
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
33
#include <base_struct.h>
34
#include <worksheet.h>
35
#include <worksheet_shape_builder.h>
36
#include <class_worksheet_dataitem.h>
38
#include <page_layout_reader_lexer.h>
40
#include <base_units.h>
43
using namespace TB_READER_T;
45
#define double2Str Double2Str
47
// A helper function to write tokens:
48
static const char* getTokenName( T aTok )
50
return PAGE_LAYOUT_READER_LEXER::TokenName( aTok );
53
// A basic helper class to write a page layout description
54
// Not used alone, a file writer or a string writer should be
56
// Therefore the constructor is protected
57
class WORKSHEET_LAYOUT_IO
60
OUTPUTFORMATTER* m_out;
62
WORKSHEET_LAYOUT_IO() {}
63
virtual ~WORKSHEET_LAYOUT_IO() {}
66
void Format( WORKSHEET_LAYOUT* aPageLayout ) const
69
void Format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
73
void format( WORKSHEET_LAYOUT* aPageLayout ) const
76
void format( WORKSHEET_DATAITEM_TEXT* aItem, int aNestLevel ) const throw( IO_ERROR );
77
void format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const throw( IO_ERROR );
78
void format( WORKSHEET_DATAITEM_POLYPOLYGON* aItem, int aNestLevel )
79
const throw( IO_ERROR );
80
void formatCoordinate( const char * aToken, POINT_COORD & aCoord ) const
82
void formatRepeatParameters( WORKSHEET_DATAITEM* aItem ) const throw( IO_ERROR );
83
void formatOptions( WORKSHEET_DATAITEM* aItem ) const throw( IO_ERROR );
86
// A helper class to write a page layout description to a file
87
class WORKSHEET_LAYOUT_FILEIO: public WORKSHEET_LAYOUT_IO
89
FILE_OUTPUTFORMATTER * m_fileout;
92
WORKSHEET_LAYOUT_FILEIO( const wxString& aFilename ):
97
m_fileout = new FILE_OUTPUTFORMATTER( aFilename );
100
catch( IO_ERROR ioe )
102
wxMessageBox( ioe.errorText, _("Write Page Layout Error" ) );
106
~WORKSHEET_LAYOUT_FILEIO()
112
// A helper class to write a page layout description to a string
113
class WORKSHEET_LAYOUT_STRINGIO: public WORKSHEET_LAYOUT_IO
115
STRING_FORMATTER * m_writer;
119
WORKSHEET_LAYOUT_STRINGIO( wxString& aOutputString ):
120
WORKSHEET_LAYOUT_IO(), m_output( aOutputString )
124
m_writer = new STRING_FORMATTER();
127
catch( IO_ERROR ioe )
129
wxMessageBox( ioe.errorText, _("Write Page Layout Error" ) );
133
~WORKSHEET_LAYOUT_STRINGIO()
135
m_output = FROM_UTF8( m_writer->GetString().c_str() );
141
* Save the description in a file
143
void WORKSHEET_LAYOUT::Save( const wxString& aFullFileName )
145
WORKSHEET_LAYOUT_FILEIO writer( aFullFileName );
146
writer.Format( this );
149
/* Save the description in a buffer
151
void WORKSHEET_LAYOUT::SaveInString( wxString& aOutputString )
153
WORKSHEET_LAYOUT_STRINGIO writer( aOutputString );
154
writer.Format( this );
158
void WORKSHEET_LAYOUT_IO::Format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
161
switch( aItem->GetType() )
163
case WORKSHEET_DATAITEM::WS_TEXT:
164
format( (WORKSHEET_DATAITEM_TEXT*) aItem, aNestLevel );
167
case WORKSHEET_DATAITEM::WS_SEGMENT:
168
case WORKSHEET_DATAITEM::WS_RECT:
169
format( aItem, aNestLevel );
172
case WORKSHEET_DATAITEM::WS_POLYPOLYGON:
173
format( (WORKSHEET_DATAITEM_POLYPOLYGON*) aItem, aNestLevel );
177
wxFAIL_MSG( wxT( "Cannot format item" ) );
181
void WORKSHEET_LAYOUT_IO::Format( WORKSHEET_LAYOUT* aPageLayout ) const
184
LOCALE_IO toggle; // switch on/off the locale "C" notation
186
m_out->Print( 0, "( page_layout\n" );
190
// Write default values:
191
m_out->Print( nestLevel, "(%s", getTokenName( T_setup ) );
192
m_out->Print( 0, "(textsize %s %s)",
193
double2Str( WORKSHEET_DATAITEM::m_DefaultTextSize.x ).c_str(),
194
double2Str( WORKSHEET_DATAITEM::m_DefaultTextSize.y ).c_str() );
195
m_out->Print( 0, "(linewidth %s)", double2Str( WORKSHEET_DATAITEM::m_DefaultLineWidth ).c_str() );
196
m_out->Print( 0, "(textlinewidth %s)", double2Str( WORKSHEET_DATAITEM::m_DefaultTextThickness ).c_str() );
197
m_out->Print( 0, "\n" );
199
// Write margin values
200
m_out->Print( nestLevel, "(%s %s)", getTokenName( T_left_margin ),
201
double2Str( aPageLayout->GetLeftMargin() ).c_str() );
202
m_out->Print( 0, "(%s %s)", getTokenName( T_right_margin ),
203
double2Str( aPageLayout->GetRightMargin() ).c_str() );
204
m_out->Print( 0, "(%s %s)", getTokenName( T_top_margin ),
205
double2Str( aPageLayout->GetTopMargin() ).c_str() );
206
m_out->Print( 0, "(%s %s)", getTokenName( T_bottom_margin ),
207
double2Str( aPageLayout->GetBottomMargin() ).c_str() );
208
m_out->Print( 0, ")\n" );
210
// Save the graphical items on the page layout
211
for( unsigned ii = 0; ii < aPageLayout->GetCount(); ii++ )
213
WORKSHEET_DATAITEM* item = aPageLayout->GetItem( ii );
214
Format( item, nestLevel );
217
m_out->Print( 0, ")\n" );
220
void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_TEXT* aItem, int aNestLevel ) const
223
m_out->Print( aNestLevel, "(%s", getTokenName( T_tbtext ) );
224
m_out->Print( 0, " %s", m_out->Quotew( aItem->m_TextBase ).c_str() );
225
m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
226
m_out->Quotew( aItem->m_Name ).c_str() );
228
formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
229
formatOptions( aItem );
231
if( aItem->m_Orient )
232
m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
233
double2Str(aItem->m_Orient ).c_str() );
236
bool write_size = aItem->m_TextSize.x != 0.0 && aItem->m_TextSize.y != 0.0;
237
if( write_size || aItem->IsBold() || aItem->IsItalic() )
239
m_out->Print( 0, " (%s", getTokenName( T_font ) );
243
m_out->Print( 0, " (%s %s %s)", getTokenName( T_size ),
244
double2Str(aItem->m_TextSize.x ).c_str(),
245
double2Str(aItem->m_TextSize.y ).c_str() );
247
if( aItem->IsBold() )
248
m_out->Print( 0, " %s", getTokenName( T_bold ) );
250
if( aItem->IsItalic() )
251
m_out->Print( 0, " %s", getTokenName( T_italic ) );
253
m_out->Print( 0, ")" );
256
// Write text justification
257
if( aItem->m_Hjustify != GR_TEXT_HJUSTIFY_LEFT ||
258
aItem->m_Vjustify != GR_TEXT_VJUSTIFY_CENTER )
260
m_out->Print( 0, " (%s", getTokenName( T_justify ) );
262
// Write T_center opt first, because it is
263
// also a center for both m_Hjustify and m_Vjustify
264
if( aItem->m_Hjustify == GR_TEXT_HJUSTIFY_CENTER )
265
m_out->Print( 0, " %s", getTokenName( T_center ) );
267
if( aItem->m_Hjustify == GR_TEXT_HJUSTIFY_RIGHT )
268
m_out->Print( 0, " %s", getTokenName( T_right ) );
270
if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_TOP )
271
m_out->Print( 0, " %s", getTokenName( T_top ) );
273
if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_BOTTOM )
274
m_out->Print( 0, " %s", getTokenName( T_bottom ) );
276
m_out->Print( 0, ")" );
280
if( aItem->m_BoundingBoxSize.x )
281
m_out->Print( 0, " (%s %s)", getTokenName( T_maxlen ),
282
double2Str(aItem->m_BoundingBoxSize.x ).c_str() );
284
if( aItem->m_BoundingBoxSize.y )
285
m_out->Print( 0, " (%s %s)", getTokenName( T_maxheight ),
286
double2Str(aItem->m_BoundingBoxSize.y ).c_str() );
288
formatRepeatParameters( aItem );
290
m_out->Print( 0, ")\n" );
293
void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
296
if( aItem->GetType() == WORKSHEET_DATAITEM::WS_RECT )
297
m_out->Print( aNestLevel, "(%s", getTokenName( T_rect ) );
299
m_out->Print( aNestLevel, "(%s", getTokenName( T_line ) );
301
m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
302
m_out->Quotew( aItem->m_Name ).c_str() );
304
formatCoordinate( getTokenName( T_start ), aItem->m_Pos );
305
formatCoordinate( getTokenName( T_end ), aItem->m_End );
306
formatOptions( aItem );
308
if( aItem->m_LineWidth && aItem->m_LineWidth != aItem->m_DefaultLineWidth )
309
m_out->Print( 0, " (linewidth %s)", double2Str( aItem->m_LineWidth ).c_str() );
311
formatRepeatParameters( aItem );
313
m_out->Print( 0, ")\n" );
317
void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_POLYPOLYGON* aItem, int aNestLevel ) const
320
m_out->Print( aNestLevel, "( %s", getTokenName( T_polygon ) );
321
m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
322
m_out->Quotew( aItem->m_Name ).c_str() );
323
formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
324
formatOptions( aItem );
326
formatRepeatParameters( aItem );
328
if( aItem->m_Orient )
329
m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
330
double2Str(aItem->m_Orient ).c_str() );
332
if( aItem->m_LineWidth )
333
m_out->Print( 0, " (linewidth %s)\n", double2Str( aItem->m_LineWidth ).c_str() );
335
// Write polygon corners list
336
for( int kk = 0; kk < aItem->GetPolyCount(); kk++ )
338
m_out->Print( aNestLevel+1, "( %s", getTokenName( T_pts ) );
339
// Create current polygon corners list
340
unsigned ist = aItem->GetPolyIndexStart( kk );
341
unsigned iend = aItem->GetPolyIndexEnd( kk );
345
DPOINT pos = aItem->m_Corners[ist++];
350
m_out->Print( 0, "\n" );
351
nestLevel = aNestLevel+2;
354
m_out->Print( nestLevel, " (%s %s %s)", getTokenName( T_xy ),
355
double2Str( pos.x ).c_str(),
356
double2Str( pos.y ).c_str() );
358
m_out->Print( 0, ")\n" );
361
m_out->Print( aNestLevel, ")\n" );
364
void WORKSHEET_LAYOUT_IO::formatCoordinate( const char * aToken,
365
POINT_COORD & aCoord ) const
368
m_out->Print( 0, " (%s %s %s", aToken,
369
double2Str( aCoord.m_Pos.x ).c_str(),
370
double2Str( aCoord.m_Pos.y ).c_str() );
372
switch( aCoord.m_Anchor )
378
m_out->Print( 0, " %s", getTokenName(T_ltcorner ) );
382
m_out->Print( 0, " %s", getTokenName(T_lbcorner ) );
386
m_out->Print( 0, " %s", getTokenName(T_rtcorner ) );
390
m_out->Print( 0, ")" );
393
void WORKSHEET_LAYOUT_IO::formatRepeatParameters( WORKSHEET_DATAITEM* aItem ) const
396
if( aItem->m_RepeatCount <= 1 )
399
m_out->Print( 0, " (repeat %d)", aItem->m_RepeatCount );
401
if( aItem->m_IncrementVector.x )
402
m_out->Print( 0, " (incrx %s)", double2Str(aItem-> m_IncrementVector.x ).c_str() );
404
if( aItem->m_IncrementVector.y )
405
m_out->Print( 0, " (incry %s)", double2Str( aItem->m_IncrementVector.y ).c_str() );
407
if( aItem->m_IncrementLabel != 1 &&
408
aItem->GetType() == WORKSHEET_DATAITEM::WS_TEXT )
409
m_out->Print( 0, " (incrlabel %d)", aItem->m_IncrementLabel );
412
void WORKSHEET_LAYOUT_IO::formatOptions( WORKSHEET_DATAITEM* aItem ) const
415
switch( aItem->GetPage1Option() )
422
m_out->Print( 0, " (%s %s)", getTokenName(T_option ),
423
getTokenName(T_page1only ) );
427
m_out->Print( 0, " (%s %s)", getTokenName(T_option ),
428
getTokenName(T_notonpage1 ) );