~cern-kicad/kicad/kicad-pns-tom

« back to all changes in this revision

Viewing changes to pagelayout_editor/page_layout_writer.cpp

  • Committer: Maciej Suminski
  • Date: 2013-08-02 13:57:24 UTC
  • mfrom: (4024.1.238 kicad)
  • mto: This revision was merged to the branch mainline in revision 4221.
  • Revision ID: maciej.suminski@cern.ch-20130802135724-gix6orezshkukodv
Upstream merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
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
 
5
 */
 
6
 
 
7
/*
 
8
 * This program source code file is part of KiCad, a free EDA CAD application.
 
9
 *
 
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.
 
12
 *
 
13
 *
 
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.
 
18
 *
 
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.
 
23
 *
 
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
 
30
 */
 
31
 
 
32
#include <fctsys.h>
 
33
#include <base_struct.h>
 
34
#include <worksheet.h>
 
35
#include <worksheet_shape_builder.h>
 
36
#include <class_worksheet_dataitem.h>
 
37
#include <vector2d.h>
 
38
#include <page_layout_reader_lexer.h>
 
39
#include <macros.h>
 
40
#include <base_units.h>
 
41
 
 
42
 
 
43
using namespace TB_READER_T;
 
44
 
 
45
#define double2Str Double2Str
 
46
 
 
47
// A helper function to write tokens:
 
48
static const char* getTokenName( T aTok )
 
49
{
 
50
    return PAGE_LAYOUT_READER_LEXER::TokenName( aTok );
 
51
}
 
52
 
 
53
// A basic helper class to write a page layout description
 
54
// Not used alone, a file writer or a string writer should be
 
55
// derived to use it
 
56
// Therefore the constructor is protected
 
57
class WORKSHEET_LAYOUT_IO
 
58
{
 
59
protected:
 
60
    OUTPUTFORMATTER* m_out;
 
61
 
 
62
    WORKSHEET_LAYOUT_IO() {}
 
63
    virtual ~WORKSHEET_LAYOUT_IO() {}
 
64
 
 
65
public:
 
66
    void Format( WORKSHEET_LAYOUT* aPageLayout ) const
 
67
        throw( IO_ERROR );
 
68
 
 
69
    void Format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
 
70
        throw( IO_ERROR );
 
71
 
 
72
private:
 
73
    void format( WORKSHEET_LAYOUT* aPageLayout ) const
 
74
        throw( IO_ERROR );
 
75
 
 
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
 
81
                           throw( IO_ERROR );
 
82
    void formatRepeatParameters( WORKSHEET_DATAITEM* aItem ) const throw( IO_ERROR );
 
83
    void formatOptions( WORKSHEET_DATAITEM* aItem ) const throw( IO_ERROR );
 
84
};
 
85
 
 
86
// A helper class to write a page layout description to a file
 
87
class WORKSHEET_LAYOUT_FILEIO: public WORKSHEET_LAYOUT_IO
 
88
{
 
89
    FILE_OUTPUTFORMATTER * m_fileout;
 
90
 
 
91
public:
 
92
    WORKSHEET_LAYOUT_FILEIO( const wxString& aFilename ):
 
93
        WORKSHEET_LAYOUT_IO()
 
94
    {
 
95
        try
 
96
        {
 
97
            m_fileout = new FILE_OUTPUTFORMATTER( aFilename );
 
98
            m_out = m_fileout;
 
99
        }
 
100
        catch( IO_ERROR ioe )
 
101
        {
 
102
            wxMessageBox( ioe.errorText, _("Write Page Layout Error" ) );
 
103
        }
 
104
    }
 
105
 
 
106
    ~WORKSHEET_LAYOUT_FILEIO()
 
107
    {
 
108
        delete m_fileout;
 
109
    }
 
110
};
 
111
 
 
112
// A helper class to write a page layout description to a string
 
113
class WORKSHEET_LAYOUT_STRINGIO: public WORKSHEET_LAYOUT_IO
 
114
{
 
115
    STRING_FORMATTER * m_writer;
 
116
    wxString & m_output;
 
117
 
 
118
public:
 
119
    WORKSHEET_LAYOUT_STRINGIO( wxString& aOutputString ):
 
120
        WORKSHEET_LAYOUT_IO(), m_output( aOutputString )
 
121
    {
 
122
        try
 
123
        {
 
124
            m_writer = new STRING_FORMATTER();
 
125
            m_out = m_writer;
 
126
        }
 
127
        catch( IO_ERROR ioe )
 
128
        {
 
129
            wxMessageBox( ioe.errorText, _("Write Page Layout Error" ) );
 
130
        }
 
131
    }
 
132
 
 
133
    ~WORKSHEET_LAYOUT_STRINGIO()
 
134
    {
 
135
        m_output = FROM_UTF8( m_writer->GetString().c_str() );
 
136
        delete m_writer;
 
137
    }
 
138
};
 
139
 
 
140
/*
 
141
 * Save the description in a file
 
142
 */
 
143
void WORKSHEET_LAYOUT::Save( const wxString& aFullFileName )
 
144
{
 
145
    WORKSHEET_LAYOUT_FILEIO writer( aFullFileName );
 
146
    writer.Format( this );
 
147
}
 
148
 
 
149
/* Save the description in a buffer
 
150
 */
 
151
void WORKSHEET_LAYOUT::SaveInString( wxString& aOutputString )
 
152
{
 
153
    WORKSHEET_LAYOUT_STRINGIO writer( aOutputString );
 
154
    writer.Format( this );
 
155
}
 
156
 
 
157
 
 
158
void WORKSHEET_LAYOUT_IO::Format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
 
159
    throw( IO_ERROR )
 
160
{
 
161
    switch( aItem->GetType() )
 
162
    {
 
163
    case WORKSHEET_DATAITEM::WS_TEXT:
 
164
        format( (WORKSHEET_DATAITEM_TEXT*) aItem, aNestLevel );
 
165
        break;
 
166
 
 
167
    case WORKSHEET_DATAITEM::WS_SEGMENT:
 
168
    case WORKSHEET_DATAITEM::WS_RECT:
 
169
        format( aItem, aNestLevel );
 
170
        break;
 
171
 
 
172
    case WORKSHEET_DATAITEM::WS_POLYPOLYGON:
 
173
        format( (WORKSHEET_DATAITEM_POLYPOLYGON*) aItem, aNestLevel );
 
174
        break;
 
175
 
 
176
    default:
 
177
        wxFAIL_MSG( wxT( "Cannot format item" ) );
 
178
    }
 
179
}
 
180
 
 
181
void WORKSHEET_LAYOUT_IO::Format( WORKSHEET_LAYOUT* aPageLayout ) const
 
182
    throw( IO_ERROR )
 
183
{
 
184
    LOCALE_IO   toggle;     // switch on/off the locale "C" notation
 
185
 
 
186
    m_out->Print( 0, "( page_layout\n" );
 
187
 
 
188
    // Setup
 
189
    int nestLevel = 1;
 
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" );
 
198
 
 
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" );
 
209
 
 
210
    // Save the graphical items on the page layout
 
211
    for( unsigned ii = 0; ii < aPageLayout->GetCount(); ii++ )
 
212
    {
 
213
        WORKSHEET_DATAITEM* item = aPageLayout->GetItem( ii );
 
214
        Format( item, nestLevel );
 
215
    }
 
216
 
 
217
    m_out->Print( 0, ")\n" );
 
218
}
 
219
 
 
220
void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_TEXT* aItem, int aNestLevel ) const
 
221
    throw( IO_ERROR )
 
222
{
 
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() );
 
227
 
 
228
    formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
 
229
    formatOptions( aItem );
 
230
 
 
231
    if( aItem->m_Orient )
 
232
        m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
 
233
                      double2Str(aItem->m_Orient ).c_str() );
 
234
 
 
235
    // Write font info
 
236
    bool write_size = aItem->m_TextSize.x != 0.0 && aItem->m_TextSize.y != 0.0;
 
237
    if( write_size || aItem->IsBold() || aItem->IsItalic() )
 
238
    {
 
239
        m_out->Print( 0, " (%s", getTokenName( T_font ) );
 
240
 
 
241
        if( write_size )
 
242
        {
 
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() );
 
246
        }
 
247
        if( aItem->IsBold() )
 
248
            m_out->Print( 0, " %s", getTokenName( T_bold ) );
 
249
 
 
250
        if( aItem->IsItalic() )
 
251
            m_out->Print( 0, " %s", getTokenName( T_italic ) );
 
252
 
 
253
        m_out->Print( 0, ")" );
 
254
    }
 
255
 
 
256
    // Write text justification
 
257
    if( aItem->m_Hjustify != GR_TEXT_HJUSTIFY_LEFT ||
 
258
        aItem->m_Vjustify != GR_TEXT_VJUSTIFY_CENTER )
 
259
    {
 
260
        m_out->Print( 0, " (%s", getTokenName( T_justify ) );
 
261
 
 
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 ) );
 
266
 
 
267
        if( aItem->m_Hjustify == GR_TEXT_HJUSTIFY_RIGHT )
 
268
            m_out->Print( 0, " %s", getTokenName( T_right ) );
 
269
 
 
270
        if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_TOP )
 
271
            m_out->Print( 0, " %s", getTokenName( T_top ) );
 
272
 
 
273
        if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_BOTTOM )
 
274
            m_out->Print( 0, " %s", getTokenName( T_bottom ) );
 
275
 
 
276
        m_out->Print( 0, ")" );
 
277
    }
 
278
 
 
279
    // write constraints
 
280
    if( aItem->m_BoundingBoxSize.x )
 
281
        m_out->Print( 0, " (%s %s)", getTokenName( T_maxlen ),
 
282
                      double2Str(aItem->m_BoundingBoxSize.x ).c_str() );
 
283
 
 
284
    if( aItem->m_BoundingBoxSize.y )
 
285
        m_out->Print( 0, " (%s %s)", getTokenName( T_maxheight ),
 
286
                      double2Str(aItem->m_BoundingBoxSize.y ).c_str() );
 
287
 
 
288
    formatRepeatParameters( aItem );
 
289
 
 
290
    m_out->Print( 0, ")\n" );
 
291
}
 
292
 
 
293
void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
 
294
    throw( IO_ERROR )
 
295
{
 
296
    if( aItem->GetType() == WORKSHEET_DATAITEM::WS_RECT )
 
297
        m_out->Print( aNestLevel, "(%s", getTokenName( T_rect ) );
 
298
    else
 
299
        m_out->Print( aNestLevel, "(%s", getTokenName( T_line ) );
 
300
 
 
301
    m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
 
302
                  m_out->Quotew( aItem->m_Name ).c_str() );
 
303
 
 
304
    formatCoordinate( getTokenName( T_start ), aItem->m_Pos );
 
305
    formatCoordinate( getTokenName( T_end ), aItem->m_End );
 
306
    formatOptions( aItem );
 
307
 
 
308
    if( aItem->m_LineWidth && aItem->m_LineWidth != aItem->m_DefaultLineWidth )
 
309
        m_out->Print( 0, " (linewidth %s)", double2Str( aItem->m_LineWidth ).c_str() );
 
310
 
 
311
    formatRepeatParameters( aItem );
 
312
 
 
313
    m_out->Print( 0, ")\n" );
 
314
}
 
315
 
 
316
 
 
317
void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_POLYPOLYGON* aItem, int aNestLevel ) const
 
318
    throw( IO_ERROR )
 
319
{
 
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 );
 
325
 
 
326
    formatRepeatParameters( aItem );
 
327
 
 
328
    if( aItem->m_Orient )
 
329
        m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
 
330
                      double2Str(aItem->m_Orient ).c_str() );
 
331
 
 
332
    if( aItem->m_LineWidth )
 
333
        m_out->Print( 0, " (linewidth %s)\n", double2Str( aItem->m_LineWidth ).c_str() );
 
334
 
 
335
    // Write polygon corners list
 
336
    for( int kk = 0; kk < aItem->GetPolyCount(); kk++ )
 
337
    {
 
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 );
 
342
        int ii = 0;
 
343
        while( ist <= iend )
 
344
        {
 
345
            DPOINT pos = aItem->m_Corners[ist++];
 
346
            int nestLevel = 0;
 
347
 
 
348
            if( ii++ > 4)
 
349
            {
 
350
                m_out->Print( 0, "\n" );
 
351
                nestLevel = aNestLevel+2;
 
352
                ii = 0;
 
353
            }
 
354
            m_out->Print( nestLevel, " (%s %s %s)", getTokenName( T_xy ),
 
355
                          double2Str( pos.x ).c_str(),
 
356
                          double2Str( pos.y ).c_str() );
 
357
        }
 
358
        m_out->Print( 0, ")\n" );
 
359
    }
 
360
 
 
361
    m_out->Print( aNestLevel, ")\n" );
 
362
}
 
363
 
 
364
void WORKSHEET_LAYOUT_IO::formatCoordinate( const char * aToken,
 
365
                                            POINT_COORD & aCoord ) const
 
366
                       throw( IO_ERROR )
 
367
{
 
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() );
 
371
 
 
372
    switch( aCoord.m_Anchor )
 
373
    {
 
374
        case RB_CORNER:
 
375
            break;
 
376
 
 
377
        case LT_CORNER:
 
378
            m_out->Print( 0, " %s", getTokenName(T_ltcorner ) );
 
379
            break;
 
380
 
 
381
        case LB_CORNER:
 
382
            m_out->Print( 0, " %s", getTokenName(T_lbcorner ) );
 
383
            break;
 
384
 
 
385
        case RT_CORNER:
 
386
            m_out->Print( 0, " %s", getTokenName(T_rtcorner ) );
 
387
            break;
 
388
    }
 
389
 
 
390
    m_out->Print( 0, ")" );
 
391
}
 
392
 
 
393
void WORKSHEET_LAYOUT_IO::formatRepeatParameters( WORKSHEET_DATAITEM* aItem ) const
 
394
                       throw( IO_ERROR )
 
395
{
 
396
    if( aItem->m_RepeatCount <= 1 )
 
397
        return;
 
398
 
 
399
    m_out->Print( 0, " (repeat %d)", aItem->m_RepeatCount );
 
400
 
 
401
    if( aItem->m_IncrementVector.x )
 
402
        m_out->Print( 0, " (incrx %s)", double2Str(aItem-> m_IncrementVector.x ).c_str() );
 
403
 
 
404
    if( aItem->m_IncrementVector.y )
 
405
        m_out->Print( 0, " (incry %s)", double2Str( aItem->m_IncrementVector.y ).c_str() );
 
406
 
 
407
    if( aItem->m_IncrementLabel != 1 &&
 
408
        aItem->GetType() == WORKSHEET_DATAITEM::WS_TEXT )
 
409
        m_out->Print( 0, " (incrlabel %d)", aItem->m_IncrementLabel );
 
410
}
 
411
 
 
412
void WORKSHEET_LAYOUT_IO::formatOptions( WORKSHEET_DATAITEM* aItem ) const
 
413
                       throw( IO_ERROR )
 
414
{
 
415
    switch( aItem->GetPage1Option() )
 
416
    {
 
417
        default:
 
418
        case 0:
 
419
            break;
 
420
 
 
421
        case 1:
 
422
            m_out->Print( 0, " (%s %s)", getTokenName(T_option ),
 
423
                          getTokenName(T_page1only ) );
 
424
            break;
 
425
 
 
426
        case -1:
 
427
            m_out->Print( 0, " (%s %s)", getTokenName(T_option ),
 
428
                          getTokenName(T_notonpage1 ) );
 
429
            break;
 
430
    }
 
431
}