KiCad PCB EDA Suite
page_layout_writer.cpp
Go to the documentation of this file.
1 
7 /*
8  * This program source code file is part of KiCad, a free EDA CAD application.
9  *
10  * Copyright (C) 2013-2016 CERN
11  *
12  * @author Jean-Pierre Charras, jp.charras at wanadoo.fr
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>
37 #include <math/vector2d.h>
39 #include <macros.h>
40 #include <convert_to_biu.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 {
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
58 {
59 protected:
61 
62  WORKSHEET_LAYOUT_IO() { m_out = NULL; }
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 format( WORKSHEET_DATAITEM_BITMAP* aItem, int aNestLevel ) const
81  throw( IO_ERROR );
82  void formatCoordinate( const char * aToken, POINT_COORD & aCoord ) const
83  throw( IO_ERROR );
84  void formatRepeatParameters( WORKSHEET_DATAITEM* aItem ) const throw( IO_ERROR );
85  void formatOptions( WORKSHEET_DATAITEM* aItem ) const throw( IO_ERROR );
86 };
87 
88 
89 // A helper class to write a page layout description to a file
91 {
93 
94 public:
95  WORKSHEET_LAYOUT_FILEIO( const wxString& aFilename ):
97  {
98  try
99  {
100  m_fileout = new FILE_OUTPUTFORMATTER( aFilename );
101  m_out = m_fileout;
102  }
103  catch( const IO_ERROR& ioe )
104  {
105  wxMessageBox( ioe.What(), _( "Error writing page layout descr file" ) );
106  }
107  }
108 
110  {
111  delete m_fileout;
112  }
113 };
114 
115 
116 // A helper class to write a page layout description to a string
118 {
120  wxString & m_output;
121 
122 public:
123  WORKSHEET_LAYOUT_STRINGIO( wxString& aOutputString ):
124  WORKSHEET_LAYOUT_IO(), m_output( aOutputString )
125  {
126  try
127  {
128  m_writer = new STRING_FORMATTER();
129  m_out = m_writer;
130  }
131  catch( const IO_ERROR& ioe )
132  {
133  wxMessageBox( ioe.What(), _( "Error writing page layout descr file" ) );
134  }
135  }
136 
138  {
139  m_output = FROM_UTF8( m_writer->GetString().c_str() );
140  delete m_writer;
141  }
142 };
143 
144 
145 /*
146  * Save the description in a file
147  */
148 void WORKSHEET_LAYOUT::Save( const wxString& aFullFileName )
149 {
150  WORKSHEET_LAYOUT_FILEIO writer( aFullFileName );
151  writer.Format( this );
152 }
153 
154 
155 /* Save the description in a buffer
156  */
157 void WORKSHEET_LAYOUT::SaveInString( wxString& aOutputString )
158 {
159  WORKSHEET_LAYOUT_STRINGIO writer( aOutputString );
160  writer.Format( this );
161 }
162 
163 
164 void WORKSHEET_LAYOUT_IO::Format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
165  throw( IO_ERROR )
166 {
167  switch( aItem->GetType() )
168  {
170  format( (WORKSHEET_DATAITEM_TEXT*) aItem, aNestLevel );
171  break;
172 
175  format( aItem, aNestLevel );
176  break;
177 
179  format( (WORKSHEET_DATAITEM_POLYPOLYGON*) aItem, aNestLevel );
180  break;
181 
183  format( (WORKSHEET_DATAITEM_BITMAP*) aItem, aNestLevel );
184  break;
185 
186  default:
187  wxFAIL_MSG( wxT( "Cannot format item" ) );
188  }
189 }
190 
191 
193  throw( IO_ERROR )
194 {
195  LOCALE_IO toggle; // switch on/off the locale "C" notation
196 
197  m_out->Print( 0, "(page_layout\n" );
198 
199  // Setup
200  int nestLevel = 1;
201  // Write default values:
202  m_out->Print( nestLevel, "(%s ", getTokenName( T_setup ) );
203  m_out->Print( 0, "(textsize %s %s)",
206  m_out->Print( 0, "(linewidth %s)", double2Str( WORKSHEET_DATAITEM::m_DefaultLineWidth ).c_str() );
207  m_out->Print( 0, "(textlinewidth %s)", double2Str( WORKSHEET_DATAITEM::m_DefaultTextThickness ).c_str() );
208  m_out->Print( 0, "\n" );
209 
210  // Write margin values
211  m_out->Print( nestLevel, "(%s %s)", getTokenName( T_left_margin ),
212  double2Str( aPageLayout->GetLeftMargin() ).c_str() );
213  m_out->Print( 0, "(%s %s)", getTokenName( T_right_margin ),
214  double2Str( aPageLayout->GetRightMargin() ).c_str() );
215  m_out->Print( 0, "(%s %s)", getTokenName( T_top_margin ),
216  double2Str( aPageLayout->GetTopMargin() ).c_str() );
217  m_out->Print( 0, "(%s %s)", getTokenName( T_bottom_margin ),
218  double2Str( aPageLayout->GetBottomMargin() ).c_str() );
219  m_out->Print( 0, ")\n" );
220 
221  // Save the graphical items on the page layout
222  for( unsigned ii = 0; ii < aPageLayout->GetCount(); ii++ )
223  {
224  WORKSHEET_DATAITEM* item = aPageLayout->GetItem( ii );
225  Format( item, nestLevel );
226  }
227 
228  m_out->Print( 0, ")\n" );
229 }
230 
231 
232 void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_TEXT* aItem, int aNestLevel ) const
233  throw( IO_ERROR )
234 {
235  m_out->Print( aNestLevel, "(%s", getTokenName( T_tbtext ) );
236  m_out->Print( 0, " %s", m_out->Quotew( aItem->m_TextBase ).c_str() );
237  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
238  m_out->Quotew( aItem->m_Name ).c_str() );
239 
240  formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
241  formatOptions( aItem );
242 
243  if( aItem->m_Orient )
244  m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
245  double2Str(aItem->m_Orient ).c_str() );
246 
247  // Write font info, only if it is not the default setup
248  bool write_size = aItem->m_TextSize.x != 0.0 || aItem->m_TextSize.y != 0.0;
249  bool write_thickness = aItem->m_LineWidth != 0.0;
250 
251  if( write_thickness || write_size || aItem->IsBold() || aItem->IsItalic() )
252  {
253  m_out->Print( 0, " (%s", getTokenName( T_font ) );
254 
255  if( write_thickness )
256  {
257  m_out->Print( 0, " (%s %s)", getTokenName( T_linewidth ),
258  double2Str(aItem->m_LineWidth ).c_str() );
259  }
260 
261  if( write_size )
262  {
263  m_out->Print( 0, " (%s %s %s)", getTokenName( T_size ),
264  double2Str(aItem->m_TextSize.x ).c_str(),
265  double2Str(aItem->m_TextSize.y ).c_str() );
266  }
267  if( aItem->IsBold() )
268  m_out->Print( 0, " %s", getTokenName( T_bold ) );
269 
270  if( aItem->IsItalic() )
271  m_out->Print( 0, " %s", getTokenName( T_italic ) );
272 
273  m_out->Print( 0, ")" );
274  }
275 
276  // Write text justification
277  if( aItem->m_Hjustify != GR_TEXT_HJUSTIFY_LEFT ||
278  aItem->m_Vjustify != GR_TEXT_VJUSTIFY_CENTER )
279  {
280  m_out->Print( 0, " (%s", getTokenName( T_justify ) );
281 
282  // Write T_center opt first, because it is
283  // also a center for both m_Hjustify and m_Vjustify
284  if( aItem->m_Hjustify == GR_TEXT_HJUSTIFY_CENTER )
285  m_out->Print( 0, " %s", getTokenName( T_center ) );
286 
287  if( aItem->m_Hjustify == GR_TEXT_HJUSTIFY_RIGHT )
288  m_out->Print( 0, " %s", getTokenName( T_right ) );
289 
290  if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_TOP )
291  m_out->Print( 0, " %s", getTokenName( T_top ) );
292 
293  if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_BOTTOM )
294  m_out->Print( 0, " %s", getTokenName( T_bottom ) );
295 
296  m_out->Print( 0, ")" );
297  }
298 
299  // write constraints
300  if( aItem->m_BoundingBoxSize.x )
301  m_out->Print( 0, " (%s %s)", getTokenName( T_maxlen ),
302  double2Str(aItem->m_BoundingBoxSize.x ).c_str() );
303 
304  if( aItem->m_BoundingBoxSize.y )
305  m_out->Print( 0, " (%s %s)", getTokenName( T_maxheight ),
306  double2Str(aItem->m_BoundingBoxSize.y ).c_str() );
307 
308  formatRepeatParameters( aItem );
309 
310  m_out->Print( 0, ")\n" );
311 }
312 
313 void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
314  throw( IO_ERROR )
315 {
316  if( aItem->GetType() == WORKSHEET_DATAITEM::WS_RECT )
317  m_out->Print( aNestLevel, "(%s", getTokenName( T_rect ) );
318  else
319  m_out->Print( aNestLevel, "(%s", getTokenName( T_line ) );
320 
321  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
322  m_out->Quotew( aItem->m_Name ).c_str() );
323 
324  formatCoordinate( getTokenName( T_start ), aItem->m_Pos );
325  formatCoordinate( getTokenName( T_end ), aItem->m_End );
326  formatOptions( aItem );
327 
328  if( aItem->m_LineWidth && aItem->m_LineWidth != aItem->m_DefaultLineWidth )
329  m_out->Print( 0, " (linewidth %s)", double2Str( aItem->m_LineWidth ).c_str() );
330 
331  formatRepeatParameters( aItem );
332 
333  m_out->Print( 0, ")\n" );
334 }
335 
336 
338  throw( IO_ERROR )
339 {
340  m_out->Print( aNestLevel, "(%s", getTokenName( T_polygon ) );
341  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
342  m_out->Quotew( aItem->m_Name ).c_str() );
343  formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
344  formatOptions( aItem );
345 
346  formatRepeatParameters( aItem );
347 
348  if( aItem->m_Orient )
349  m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
350  double2Str(aItem->m_Orient ).c_str() );
351 
352  if( aItem->m_LineWidth )
353  m_out->Print( 0, " (linewidth %s)\n", double2Str( aItem->m_LineWidth ).c_str() );
354 
355  // Write polygon corners list
356  for( int kk = 0; kk < aItem->GetPolyCount(); kk++ )
357  {
358  m_out->Print( aNestLevel+1, "(%s", getTokenName( T_pts ) );
359  // Create current polygon corners list
360  unsigned ist = aItem->GetPolyIndexStart( kk );
361  unsigned iend = aItem->GetPolyIndexEnd( kk );
362  int ii = 0;
363 
364  while( ist <= iend )
365  {
366  DPOINT pos = aItem->m_Corners[ist++];
367  int nestLevel = 0;
368 
369  if( ii++ > 4)
370  {
371  m_out->Print( 0, "\n" );
372  nestLevel = aNestLevel+2;
373  ii = 0;
374  }
375 
376  m_out->Print( nestLevel, " (%s %s %s)", getTokenName( T_xy ),
377  double2Str( pos.x ).c_str(),
378  double2Str( pos.y ).c_str() );
379  }
380 
381  m_out->Print( 0, ")\n" );
382  }
383 
384  m_out->Print( aNestLevel, ")\n" );
385 }
386 
387 
388 void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_BITMAP* aItem, int aNestLevel ) const
389  throw( IO_ERROR )
390 {
391  m_out->Print( aNestLevel, "(%s", getTokenName( T_bitmap ) );
392  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
393  m_out->Quotew( aItem->m_Name ).c_str() );
394  formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
395  formatOptions( aItem );
396 
397  m_out->Print( 0, " (%s %s)", getTokenName( T_scale ),
398  double2Str( aItem->m_ImageBitmap->GetScale() ).c_str() );
399 
400  formatRepeatParameters( aItem );
401  m_out->Print( 0,"\n");
402 
403  // Write image in png readable format
404  m_out->Print( aNestLevel, "(%s\n", getTokenName( T_pngdata ) );
405  wxArrayString pngStrings;
406  aItem->m_ImageBitmap->SaveData( pngStrings );
407 
408  for( unsigned ii = 0; ii < pngStrings.GetCount(); ii++ )
409  m_out->Print( aNestLevel+1, "(data \"%s\")\n", TO_UTF8(pngStrings[ii]) );
410 
411  m_out->Print( aNestLevel+1, ")\n" );
412 
413  m_out->Print( aNestLevel, ")\n" );
414 }
415 
416 
417 void WORKSHEET_LAYOUT_IO::formatCoordinate( const char * aToken,
418  POINT_COORD & aCoord ) const
419  throw( IO_ERROR )
420 {
421  m_out->Print( 0, " (%s %s %s", aToken,
422  double2Str( aCoord.m_Pos.x ).c_str(),
423  double2Str( aCoord.m_Pos.y ).c_str() );
424 
425  switch( aCoord.m_Anchor )
426  {
427  case RB_CORNER:
428  break;
429 
430  case LT_CORNER:
431  m_out->Print( 0, " %s", getTokenName( T_ltcorner ) );
432  break;
433 
434  case LB_CORNER:
435  m_out->Print( 0, " %s", getTokenName( T_lbcorner ) );
436  break;
437 
438  case RT_CORNER:
439  m_out->Print( 0, " %s", getTokenName( T_rtcorner ) );
440  break;
441  }
442 
443  m_out->Print( 0, ")" );
444 }
445 
446 
448  throw( IO_ERROR )
449 {
450  if( aItem->m_RepeatCount <= 1 )
451  return;
452 
453  m_out->Print( 0, " (repeat %d)", aItem->m_RepeatCount );
454 
455  if( aItem->m_IncrementVector.x )
456  m_out->Print( 0, " (incrx %s)", double2Str(aItem-> m_IncrementVector.x ).c_str() );
457 
458  if( aItem->m_IncrementVector.y )
459  m_out->Print( 0, " (incry %s)", double2Str( aItem->m_IncrementVector.y ).c_str() );
460 
461  if( aItem->m_IncrementLabel != 1 &&
462  aItem->GetType() == WORKSHEET_DATAITEM::WS_TEXT )
463  m_out->Print( 0, " (incrlabel %d)", aItem->m_IncrementLabel );
464 }
465 
466 
468  throw( IO_ERROR )
469 {
470  switch( aItem->GetPage1Option() )
471  {
472  default:
473  case 0:
474  break;
475 
476  case 1:
477  m_out->Print( 0, " (%s %s)", getTokenName( T_option ),
479  break;
480 
481  case -1:
482  m_out->Print( 0, " (%s %s)", getTokenName( T_option ), getTokenName( T_notonpage1 ) );
483  break;
484  }
485 }
#define double2Str
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
Class LOCALE_IO is a class that can be instantiated within a scope in which you are expecting excepti...
Definition: common.h:166
WORKSHEET_LAYOUT_STRINGIO(wxString &aOutputString)
OUTPUTFORMATTER * m_out
description of graphic items and texts to build a title block
void formatOptions(WORKSHEET_DATAITEM *aItem) const
WORKSHEET_LAYOUT_FILEIO(const wxString &aFilename)
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
void Save(const wxString &aFullFileName)
Save the description in a file.
FILE_OUTPUTFORMATTER * m_fileout
void formatRepeatParameters(WORKSHEET_DATAITEM *aItem) const
This file contains miscellaneous commonly used macros and functions.
void format(WORKSHEET_LAYOUT *aPageLayout) const
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
C++ does not put enum values in separate namespaces unless the enum itself is in a separate namespace...
void Format(WORKSHEET_LAYOUT *aPageLayout) const
const std::string & GetString()
Definition: richio.h:475
std::string Quotew(const wxString &aWrapee)
Definition: richio.cpp:486
static const char * TokenName(TB_READER_T::T aTok)
Function TokenName returns the name of the token in ASCII form.
WORKSHEET_LAYOUT handles the graphic items list to draw/plot the title block and other items (page re...
void SaveInString(wxString &aOutputString)
Save the description in a buffer.
static double m_DefaultTextThickness
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
static const char * getTokenName(T aTok)
T
enum T contains all this lexer's tokens.
Class FILE_OUTPUTFORMATTER may be used for text file output.
Definition: richio.h:492
classes and function to generate graphics to plt or draw titles blocks and frame references ...
Basic classes for most KiCad items.
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:408
Class STRING_FORMATTER implements OUTPUTFORMATTER to a memory buffer.
Definition: richio.h:445
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
void formatCoordinate(const char *aToken, POINT_COORD &aCoord) const