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 
68  void Format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const;
69 
70 private:
71  void format( WORKSHEET_LAYOUT* aPageLayout ) const;
72 
73  void format( WORKSHEET_DATAITEM_TEXT* aItem, int aNestLevel ) const;
74  void format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const;
75  void format( WORKSHEET_DATAITEM_POLYPOLYGON* aItem, int aNestLevel )
76  const;
77  void format( WORKSHEET_DATAITEM_BITMAP* aItem, int aNestLevel ) const;
78  void formatCoordinate( const char * aToken, POINT_COORD & aCoord ) const;
79  void formatRepeatParameters( WORKSHEET_DATAITEM* aItem ) const;
80  void formatOptions( WORKSHEET_DATAITEM* aItem ) const;
81 };
82 
83 
84 // A helper class to write a page layout description to a file
86 {
88 
89 public:
90  WORKSHEET_LAYOUT_FILEIO( const wxString& aFilename ):
92  {
93  try
94  {
95  m_fileout = new FILE_OUTPUTFORMATTER( aFilename );
96  m_out = m_fileout;
97  }
98  catch( const IO_ERROR& ioe )
99  {
100  wxMessageBox( ioe.What(), _( "Error writing page layout descr file" ) );
101  }
102  }
103 
105  {
106  delete m_fileout;
107  }
108 };
109 
110 
111 // A helper class to write a page layout description to a string
113 {
115  wxString & m_output;
116 
117 public:
118  WORKSHEET_LAYOUT_STRINGIO( wxString& aOutputString ):
119  WORKSHEET_LAYOUT_IO(), m_output( aOutputString )
120  {
121  try
122  {
123  m_writer = new STRING_FORMATTER();
124  m_out = m_writer;
125  }
126  catch( const IO_ERROR& ioe )
127  {
128  wxMessageBox( ioe.What(), _( "Error writing page layout descr file" ) );
129  }
130  }
131 
133  {
134  m_output = FROM_UTF8( m_writer->GetString().c_str() );
135  delete m_writer;
136  }
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 
150 /* Save the description in a buffer
151  */
152 void WORKSHEET_LAYOUT::SaveInString( wxString& aOutputString )
153 {
154  WORKSHEET_LAYOUT_STRINGIO writer( aOutputString );
155  writer.Format( this );
156 }
157 
158 
159 void WORKSHEET_LAYOUT_IO::Format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
160 {
161  switch( aItem->GetType() )
162  {
164  format( (WORKSHEET_DATAITEM_TEXT*) aItem, aNestLevel );
165  break;
166 
169  format( aItem, aNestLevel );
170  break;
171 
173  format( (WORKSHEET_DATAITEM_POLYPOLYGON*) aItem, aNestLevel );
174  break;
175 
177  format( (WORKSHEET_DATAITEM_BITMAP*) aItem, aNestLevel );
178  break;
179 
180  default:
181  wxFAIL_MSG( wxT( "Cannot format item" ) );
182  }
183 }
184 
185 
187 {
188  LOCALE_IO toggle; // switch on/off the locale "C" notation
189 
190  m_out->Print( 0, "(page_layout\n" );
191 
192  // Setup
193  int nestLevel = 1;
194  // Write default values:
195  m_out->Print( nestLevel, "(%s ", getTokenName( T_setup ) );
196  m_out->Print( 0, "(textsize %s %s)",
199  m_out->Print( 0, "(linewidth %s)", double2Str( WORKSHEET_DATAITEM::m_DefaultLineWidth ).c_str() );
200  m_out->Print( 0, "(textlinewidth %s)", double2Str( WORKSHEET_DATAITEM::m_DefaultTextThickness ).c_str() );
201  m_out->Print( 0, "\n" );
202 
203  // Write margin values
204  m_out->Print( nestLevel, "(%s %s)", getTokenName( T_left_margin ),
205  double2Str( aPageLayout->GetLeftMargin() ).c_str() );
206  m_out->Print( 0, "(%s %s)", getTokenName( T_right_margin ),
207  double2Str( aPageLayout->GetRightMargin() ).c_str() );
208  m_out->Print( 0, "(%s %s)", getTokenName( T_top_margin ),
209  double2Str( aPageLayout->GetTopMargin() ).c_str() );
210  m_out->Print( 0, "(%s %s)", getTokenName( T_bottom_margin ),
211  double2Str( aPageLayout->GetBottomMargin() ).c_str() );
212  m_out->Print( 0, ")\n" );
213 
214  // Save the graphical items on the page layout
215  for( unsigned ii = 0; ii < aPageLayout->GetCount(); ii++ )
216  {
217  WORKSHEET_DATAITEM* item = aPageLayout->GetItem( ii );
218  Format( item, nestLevel );
219  }
220 
221  m_out->Print( 0, ")\n" );
222 }
223 
224 
225 void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_TEXT* aItem, int aNestLevel ) const
226 {
227  m_out->Print( aNestLevel, "(%s", getTokenName( T_tbtext ) );
228  m_out->Print( 0, " %s", m_out->Quotew( aItem->m_TextBase ).c_str() );
229  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
230  m_out->Quotew( aItem->m_Name ).c_str() );
231 
232  formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
233  formatOptions( aItem );
234 
235  if( aItem->m_Orient )
236  m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
237  double2Str(aItem->m_Orient ).c_str() );
238 
239  // Write font info, only if it is not the default setup
240  bool write_size = aItem->m_TextSize.x != 0.0 || aItem->m_TextSize.y != 0.0;
241  bool write_thickness = aItem->m_LineWidth != 0.0;
242 
243  if( write_thickness || write_size || aItem->IsBold() || aItem->IsItalic() )
244  {
245  m_out->Print( 0, " (%s", getTokenName( T_font ) );
246 
247  if( write_thickness )
248  {
249  m_out->Print( 0, " (%s %s)", getTokenName( T_linewidth ),
250  double2Str(aItem->m_LineWidth ).c_str() );
251  }
252 
253  if( write_size )
254  {
255  m_out->Print( 0, " (%s %s %s)", getTokenName( T_size ),
256  double2Str(aItem->m_TextSize.x ).c_str(),
257  double2Str(aItem->m_TextSize.y ).c_str() );
258  }
259  if( aItem->IsBold() )
260  m_out->Print( 0, " %s", getTokenName( T_bold ) );
261 
262  if( aItem->IsItalic() )
263  m_out->Print( 0, " %s", getTokenName( T_italic ) );
264 
265  m_out->Print( 0, ")" );
266  }
267 
268  // Write text justification
269  if( aItem->m_Hjustify != GR_TEXT_HJUSTIFY_LEFT ||
271  {
272  m_out->Print( 0, " (%s", getTokenName( T_justify ) );
273 
274  // Write T_center opt first, because it is
275  // also a center for both m_Hjustify and m_Vjustify
276  if( aItem->m_Hjustify == GR_TEXT_HJUSTIFY_CENTER )
277  m_out->Print( 0, " %s", getTokenName( T_center ) );
278 
279  if( aItem->m_Hjustify == GR_TEXT_HJUSTIFY_RIGHT )
280  m_out->Print( 0, " %s", getTokenName( T_right ) );
281 
282  if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_TOP )
283  m_out->Print( 0, " %s", getTokenName( T_top ) );
284 
285  if( aItem->m_Vjustify == GR_TEXT_VJUSTIFY_BOTTOM )
286  m_out->Print( 0, " %s", getTokenName( T_bottom ) );
287 
288  m_out->Print( 0, ")" );
289  }
290 
291  // write constraints
292  if( aItem->m_BoundingBoxSize.x )
293  m_out->Print( 0, " (%s %s)", getTokenName( T_maxlen ),
294  double2Str(aItem->m_BoundingBoxSize.x ).c_str() );
295 
296  if( aItem->m_BoundingBoxSize.y )
297  m_out->Print( 0, " (%s %s)", getTokenName( T_maxheight ),
298  double2Str(aItem->m_BoundingBoxSize.y ).c_str() );
299 
300  formatRepeatParameters( aItem );
301 
302  m_out->Print( 0, ")\n" );
303 }
304 
305 void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM* aItem, int aNestLevel ) const
306 {
307  if( aItem->GetType() == WORKSHEET_DATAITEM::WS_RECT )
308  m_out->Print( aNestLevel, "(%s", getTokenName( T_rect ) );
309  else
310  m_out->Print( aNestLevel, "(%s", getTokenName( T_line ) );
311 
312  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
313  m_out->Quotew( aItem->m_Name ).c_str() );
314 
315  formatCoordinate( getTokenName( T_start ), aItem->m_Pos );
316  formatCoordinate( getTokenName( T_end ), aItem->m_End );
317  formatOptions( aItem );
318 
319  if( aItem->m_LineWidth && aItem->m_LineWidth != aItem->m_DefaultLineWidth )
320  m_out->Print( 0, " (linewidth %s)", double2Str( aItem->m_LineWidth ).c_str() );
321 
322  formatRepeatParameters( aItem );
323 
324  m_out->Print( 0, ")\n" );
325 }
326 
327 
329 {
330  m_out->Print( aNestLevel, "(%s", getTokenName( T_polygon ) );
331  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
332  m_out->Quotew( aItem->m_Name ).c_str() );
333  formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
334  formatOptions( aItem );
335 
336  formatRepeatParameters( aItem );
337 
338  if( aItem->m_Orient )
339  m_out->Print( 0, " (%s %s)", getTokenName( T_rotate ),
340  double2Str(aItem->m_Orient ).c_str() );
341 
342  if( aItem->m_LineWidth )
343  m_out->Print( 0, " (linewidth %s)\n", double2Str( aItem->m_LineWidth ).c_str() );
344 
345  // Write polygon corners list
346  for( int kk = 0; kk < aItem->GetPolyCount(); kk++ )
347  {
348  m_out->Print( aNestLevel+1, "(%s", getTokenName( T_pts ) );
349  // Create current polygon corners list
350  unsigned ist = aItem->GetPolyIndexStart( kk );
351  unsigned iend = aItem->GetPolyIndexEnd( kk );
352  int ii = 0;
353 
354  while( ist <= iend )
355  {
356  DPOINT pos = aItem->m_Corners[ist++];
357  int nestLevel = 0;
358 
359  if( ii++ > 4)
360  {
361  m_out->Print( 0, "\n" );
362  nestLevel = aNestLevel+2;
363  ii = 0;
364  }
365 
366  m_out->Print( nestLevel, " (%s %s %s)", getTokenName( T_xy ),
367  double2Str( pos.x ).c_str(),
368  double2Str( pos.y ).c_str() );
369  }
370 
371  m_out->Print( 0, ")\n" );
372  }
373 
374  m_out->Print( aNestLevel, ")\n" );
375 }
376 
377 
378 void WORKSHEET_LAYOUT_IO::format( WORKSHEET_DATAITEM_BITMAP* aItem, int aNestLevel ) const
379 {
380  m_out->Print( aNestLevel, "(%s", getTokenName( T_bitmap ) );
381  m_out->Print( 0, " (%s %s)", getTokenName( T_name ),
382  m_out->Quotew( aItem->m_Name ).c_str() );
383  formatCoordinate( getTokenName( T_pos ), aItem->m_Pos );
384  formatOptions( aItem );
385 
386  m_out->Print( 0, " (%s %s)", getTokenName( T_scale ),
387  double2Str( aItem->m_ImageBitmap->GetScale() ).c_str() );
388 
389  formatRepeatParameters( aItem );
390  m_out->Print( 0,"\n");
391 
392  // Write image in png readable format
393  m_out->Print( aNestLevel, "(%s\n", getTokenName( T_pngdata ) );
394  wxArrayString pngStrings;
395  aItem->m_ImageBitmap->SaveData( pngStrings );
396 
397  for( unsigned ii = 0; ii < pngStrings.GetCount(); ii++ )
398  m_out->Print( aNestLevel+1, "(data \"%s\")\n", TO_UTF8(pngStrings[ii]) );
399 
400  m_out->Print( aNestLevel+1, ")\n" );
401 
402  m_out->Print( aNestLevel, ")\n" );
403 }
404 
405 
406 void WORKSHEET_LAYOUT_IO::formatCoordinate( const char * aToken,
407  POINT_COORD & aCoord ) const
408 {
409  m_out->Print( 0, " (%s %s %s", aToken,
410  double2Str( aCoord.m_Pos.x ).c_str(),
411  double2Str( aCoord.m_Pos.y ).c_str() );
412 
413  switch( aCoord.m_Anchor )
414  {
415  case RB_CORNER:
416  break;
417 
418  case LT_CORNER:
419  m_out->Print( 0, " %s", getTokenName( T_ltcorner ) );
420  break;
421 
422  case LB_CORNER:
423  m_out->Print( 0, " %s", getTokenName( T_lbcorner ) );
424  break;
425 
426  case RT_CORNER:
427  m_out->Print( 0, " %s", getTokenName( T_rtcorner ) );
428  break;
429  }
430 
431  m_out->Print( 0, ")" );
432 }
433 
434 
436 {
437  if( aItem->m_RepeatCount <= 1 )
438  return;
439 
440  m_out->Print( 0, " (repeat %d)", aItem->m_RepeatCount );
441 
442  if( aItem->m_IncrementVector.x )
443  m_out->Print( 0, " (incrx %s)", double2Str(aItem-> m_IncrementVector.x ).c_str() );
444 
445  if( aItem->m_IncrementVector.y )
446  m_out->Print( 0, " (incry %s)", double2Str( aItem->m_IncrementVector.y ).c_str() );
447 
448  if( aItem->m_IncrementLabel != 1 &&
450  m_out->Print( 0, " (incrlabel %d)", aItem->m_IncrementLabel );
451 }
452 
453 
455 {
456  switch( aItem->GetPage1Option() )
457  {
458  default:
459  case 0:
460  break;
461 
462  case 1:
463  m_out->Print( 0, " (%s %s)", getTokenName( T_option ),
465  break;
466 
467  case -1:
468  m_out->Print( 0, " (%s %s)", getTokenName( T_option ), getTokenName( T_notonpage1 ) );
469  break;
470  }
471 }
#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
bool SaveData(FILE *aFile) const
writes the bitmap data to aFile The format is png, in Hexadecimal form: If the hexadecimal data is co...
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
WORKSHEET_DATAITEM * GetItem(unsigned aIdx) const
unsigned GetPolyIndexStart(unsigned aContour) const
const std::string & GetString()
Definition: richio.h:475
double GetScale() const
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...
unsigned GetCount() const
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
WS_ItemType GetType() const
static const char * getTokenName(T aTok)
T
enum T contains all this lexer's tokens.
unsigned GetPolyIndexEnd(unsigned aContour) const
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.
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