KiCad PCB EDA Suite
page_layout_reader.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) 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>
38 
39 
40 using namespace TB_READER_T;
41 
48 {
49 public:
50  PAGE_LAYOUT_READER_PARSER( const char* aLine, const wxString& aSource );
51  void Parse( WORKSHEET_LAYOUT* aLayout );
52 
53 private:
54 
62  int parseInt( int aMin, int aMax );
63 
69  double parseDouble();
70 
71  void parseSetup( WORKSHEET_LAYOUT* aLayout );
72 
76  void parseGraphic( WORKSHEET_DATAITEM * aItem );
77 
81  void parseText( WORKSHEET_DATAITEM_TEXT * aItem );
82 
87  void parsePolygon( WORKSHEET_DATAITEM_POLYPOLYGON * aItem );
88 
92  void parsePolyOutline( WORKSHEET_DATAITEM_POLYPOLYGON * aItem );
93 
94 
98  void parseBitmap( WORKSHEET_DATAITEM_BITMAP * aItem );
99 
100  void parseCoordinate( POINT_COORD& aCoord);
101  void readOption( WORKSHEET_DATAITEM * aItem );
102  void readPngdata( WORKSHEET_DATAITEM_BITMAP * aItem );
103 };
104 
105 // PCB_PLOT_PARAMS_PARSER
106 
107 PAGE_LAYOUT_READER_PARSER::PAGE_LAYOUT_READER_PARSER( const char* aLine, const wxString& aSource ) :
108  PAGE_LAYOUT_READER_LEXER( aLine, aSource )
109 {
110 }
111 
112 
114 {
115  T token;
116  WORKSHEET_DATAITEM * item;
117 
118  LOCALE_IO toggle;
119 
120  while( ( token = NextTok() ) != T_RIGHT )
121  {
122  if( token == T_EOF)
123  break;
124 
125  if( token == T_LEFT )
126  token = NextTok();
127 
128  if( token == T_page_layout )
129  continue;
130 
131  switch( token )
132  {
133  case T_setup: // Defines default values for graphic items
134  parseSetup( aLayout );
135  break;
136 
137  case T_line:
139  parseGraphic( item );
140  aLayout->Append( item );
141  break;
142 
143  case T_rect:
145  parseGraphic( item );
146  aLayout->Append( item );
147  break;
148 
149  case T_polygon:
150  item = new WORKSHEET_DATAITEM_POLYPOLYGON();
152  aLayout->Append( item );
153  break;
154 
155  case T_bitmap:
156  item = new WORKSHEET_DATAITEM_BITMAP( NULL );
158  aLayout->Append( item );
159  break;
160 
161  case T_tbtext:
163  item = new WORKSHEET_DATAITEM_TEXT( FromUTF8() );
165  aLayout->Append( item );
166  break;
167 
168  default:
169  Unexpected( CurText() );
170  break;
171  }
172  }
173 }
174 
176 {
177  T token;
178  while( ( token = NextTok() ) != T_RIGHT )
179  {
180  if( token == T_EOF)
181  break;
182 
183  switch( token )
184  {
185  case T_LEFT:
186  break;
187 
188  case T_linewidth:
190  NeedRIGHT();
191  break;
192 
193  case T_textsize:
196  NeedRIGHT();
197  break;
198 
199  case T_textlinewidth:
201  NeedRIGHT();
202  break;
203 
204  case T_left_margin:
205  aLayout->SetLeftMargin( parseDouble() );
206  NeedRIGHT();
207  break;
208 
209  case T_right_margin:
210  aLayout->SetRightMargin( parseDouble() );
211  NeedRIGHT();
212  break;
213 
214  case T_top_margin:
215  aLayout->SetTopMargin( parseDouble() );
216  NeedRIGHT();
217  break;
218 
219  case T_bottom_margin:
220  aLayout->SetBottomMargin( parseDouble() );
221  NeedRIGHT();
222  break;
223 
224  default:
225  Unexpected( CurText() );
226  break;
227  }
228  }
229 }
230 
232 {
233  T token;
234 
235  while( ( token = NextTok() ) != T_RIGHT )
236  {
237  if( token == T_EOF)
238  break;
239 
240  if( token == T_LEFT )
241  token = NextTok();
242 
243  switch( token )
244  {
245  case T_comment:
247  aItem->m_Info = FromUTF8();
248  NeedRIGHT();
249  break;
250 
251  case T_pos:
252  parseCoordinate( aItem->m_Pos );
253  break;
254 
255  case T_name:
257  aItem->m_Name = FromUTF8();
258  NeedRIGHT();
259  break;
260 
261  case T_option:
262  readOption( aItem );
263  break;
264 
265  case T_pts:
266  parsePolyOutline( aItem );
267  aItem->CloseContour();
268  break;
269 
270  case T_rotate:
271  aItem->m_Orient = parseDouble();
272  NeedRIGHT();
273  break;
274 
275  case T_repeat:
276  aItem->m_RepeatCount = parseInt( -1, 100 );
277  NeedRIGHT();
278  break;
279 
280  case T_incrx:
281  aItem->m_IncrementVector.x = parseDouble();
282  NeedRIGHT();
283  break;
284 
285  case T_incry:
286  aItem->m_IncrementVector.y = parseDouble();
287  NeedRIGHT();
288  break;
289 
290  case T_linewidth:
291  aItem->m_LineWidth = parseDouble();
292  NeedRIGHT();
293  break;
294 
295  default:
296  Unexpected( CurText() );
297  break;
298  }
299  }
300 
301  aItem->SetBoundingBox();
302 }
303 
305 {
306  DPOINT corner;
307  T token;
308 
309  while( ( token = NextTok() ) != T_RIGHT )
310  {
311  if( token == T_EOF)
312  break;
313 
314  if( token == T_LEFT )
315  token = NextTok();
316 
317  switch( token )
318  {
319  case T_xy:
320  corner.x = parseDouble();
321  corner.y = parseDouble();
322  aItem->AppendCorner( corner );
323  NeedRIGHT();
324  break;
325 
326  default:
327  Unexpected( CurText() );
328  break;
329  }
330  }
331 }
332 
333 #include <wx/mstream.h>
335 {
336  T token;
337  BITMAP_BASE* image = new BITMAP_BASE;
338  aItem->m_ImageBitmap = image;
339 
340  while( ( token = NextTok() ) != T_RIGHT )
341  {
342  if( token == T_EOF)
343  break;
344 
345  if( token == T_LEFT )
346  token = NextTok();
347 
348  switch( token )
349  {
350  case T_name:
352  aItem->m_Name = FromUTF8();
353  NeedRIGHT();
354  break;
355 
356  case T_pos:
357  parseCoordinate( aItem->m_Pos );
358  break;
359 
360  case T_repeat:
361  aItem->m_RepeatCount = parseInt( -1, 100 );
362  NeedRIGHT();
363  break;
364 
365  case T_incrx:
366  aItem->m_IncrementVector.x = parseDouble();
367  NeedRIGHT();
368  break;
369 
370  case T_incry:
371  aItem->m_IncrementVector.y = parseDouble();
372  NeedRIGHT();
373  break;
374 
375  case T_linewidth:
376  aItem->m_LineWidth = parseDouble();
377  NeedRIGHT();
378  break;
379 
380  case T_scale:
381  aItem->m_ImageBitmap->SetScale( parseDouble() );
382  NeedRIGHT();
383  break;
384 
385  case T_pngdata:
386  readPngdata( aItem );
387  break;
388 
389  case T_option:
390  readOption( aItem );
391  break;
392 
393  default:
394  Unexpected( CurText() );
395  break;
396  }
397  }
398 }
399 
401 {
402  std::string tmp;
403  T token;
404 
405  while( ( token = NextTok() ) != T_RIGHT )
406  {
407  if( token == T_EOF)
408  break;
409 
410  if( token == T_LEFT )
411  token = NextTok();
412 
413  switch( token )
414  {
415  case T_data:
417  tmp += CurStr();
418  tmp += "\n";
419  NeedRIGHT();
420  break;
421 
422  default:
423  Unexpected( CurText() );
424  break;
425  }
426  }
427 
428  tmp += "EndData";
429 
430  wxString msg;
431  STRING_LINE_READER str_reader( tmp, wxT("Png kicad_wks data") );
432 
433  if( ! aItem->m_ImageBitmap->LoadData( str_reader, msg ) )
434  {
435  wxLogMessage(msg);
436  }
437 }
438 
439 
441 {
442  T token;
443 
444  while( ( token = NextTok() ) != T_RIGHT )
445  {
446  if( token == T_EOF)
447  break;
448 
449  switch( token )
450  {
451  case T_page1only:
452  aItem->SetPage1Option( 1 );
453  break;
454 
455  case T_notonpage1:
456  aItem->SetPage1Option( -1 );
457  break;
458 
459  default:
460  Unexpected( CurText() );
461  break;
462  }
463  }
464 }
465 
466 
468 {
469  T token;
470 
471  while( ( token = NextTok() ) != T_RIGHT )
472  {
473  if( token == T_EOF)
474  break;
475 
476  if( token == T_LEFT )
477  token = NextTok();
478  else
479  {
480  // If an other token than T_LEFT is read here, this is an error
481  // however, due to a old bug in kicad, the token T_end can be found
482  // without T_LEFT in a very few .wks files (perhaps only one in a demo).
483  // So this ugly hack disables the error detection.
484  if( token != T_end )
485  Unexpected( CurText() );
486  }
487 
488  switch( token )
489  {
490  case T_comment:
492  aItem->m_Info = FromUTF8();
493  NeedRIGHT();
494  break;
495 
496  case T_option:
497  readOption( aItem );
498  break;
499 
500  case T_name:
502  aItem->m_Name = FromUTF8();
503  NeedRIGHT();
504  break;
505 
506  case T_start:
507  parseCoordinate( aItem->m_Pos );
508  break;
509 
510  case T_end:
511  parseCoordinate( aItem->m_End );
512  break;
513 
514  case T_repeat:
515  aItem->m_RepeatCount = parseInt( -1, 100 );
516  NeedRIGHT();
517  break;
518 
519  case T_incrx:
520  aItem->m_IncrementVector.x = parseDouble();
521  NeedRIGHT();
522  break;
523 
524  case T_incry:
525  aItem->m_IncrementVector.y = parseDouble();
526  NeedRIGHT();
527  break;
528 
529  case T_linewidth:
530  aItem->m_LineWidth = parseDouble();
531  NeedRIGHT();
532  break;
533 
534  default:
535  Unexpected( CurText() );
536  break;
537  }
538  }
539 }
540 
541 
543 {
544  T token;
545 
546  while( ( token = NextTok() ) != T_RIGHT )
547  {
548  if( token == T_EOF)
549  break;
550 
551  if( token == T_LEFT )
552  token = NextTok();
553 
554  switch( token )
555  {
556  case T_comment:
558  aItem->m_Info = FromUTF8();
559  NeedRIGHT();
560  break;
561 
562  case T_option:
563  readOption( aItem );
564  break;
565 
566  case T_name:
568  aItem->m_Name = FromUTF8();
569  NeedRIGHT();
570  break;
571 
572  case T_pos:
573  parseCoordinate( aItem->m_Pos );
574  break;
575 
576  case T_repeat:
577  aItem->m_RepeatCount = parseInt( -1, 100 );
578  NeedRIGHT();
579  break;
580 
581  case T_incrx:
582  aItem->m_IncrementVector.x = parseDouble();
583  NeedRIGHT();
584  break;
585 
586  case T_incry:
587  aItem->m_IncrementVector.y = parseDouble();
588  NeedRIGHT();
589  break;
590 
591  case T_incrlabel:
592  aItem->m_IncrementLabel = parseInt(INT_MIN, INT_MAX);
593  NeedRIGHT();
594  break;
595 
596  case T_maxlen:
597  aItem->m_BoundingBoxSize.x = parseDouble();
598  NeedRIGHT();
599  break;
600 
601  case T_maxheight:
602  aItem->m_BoundingBoxSize.y = parseDouble();
603  NeedRIGHT();
604  break;
605 
606  case T_font:
607  while( ( token = NextTok() ) != T_RIGHT )
608  {
609  if( token == T_EOF)
610  break;
611 
612  switch( token )
613  {
614  case T_LEFT:
615  break;
616 
617  case T_bold:
618  aItem->SetBold( true );
619  break;
620 
621  case T_italic:
622  aItem->SetItalic( true );
623  break;
624 
625  case T_size:
626  aItem->m_TextSize.x = parseDouble();
627  aItem->m_TextSize.y = parseDouble();
628  NeedRIGHT();
629  break;
630 
631  case T_linewidth:
632  aItem->m_LineWidth = parseDouble();
633  NeedRIGHT();
634  break;
635 
636  default:
637  Unexpected( CurText() );
638  break;
639  }
640  }
641  break;
642 
643  case T_justify:
644  while( ( token = NextTok() ) != T_RIGHT )
645  {
646  if( token == T_EOF)
647  break;
648 
649  switch( token )
650  {
651  case T_center:
654  break;
655 
656  case T_left:
658  break;
659 
660  case T_right:
662  break;
663 
664  case T_top:
666  break;
667 
668  case T_bottom:
670  break;
671 
672  default:
673  Unexpected( CurText() );
674  break;
675  }
676  }
677  break;
678 
679  case T_rotate:
680  aItem->m_Orient = parseDouble();
681  NeedRIGHT();
682  break;
683 
684  default:
685  Unexpected( CurText() );
686  break;
687  }
688  }
689 }
690 
691 // parse an expression like " 25 1 ltcorner)"
693 {
694  T token;
695 
696  aCoord.m_Pos.x = parseDouble();
697  aCoord.m_Pos.y = parseDouble();
698 
699  while( ( token = NextTok() ) != T_RIGHT )
700  {
701  switch( token )
702  {
703  case T_ltcorner:
704  aCoord.m_Anchor = LT_CORNER; // left top corner
705  break;
706 
707  case T_lbcorner:
708  aCoord.m_Anchor = LB_CORNER; // left bottom corner
709  break;
710 
711  case T_rbcorner:
712  aCoord.m_Anchor = RB_CORNER; // right bottom corner
713  break;
714 
715  case T_rtcorner:
716  aCoord.m_Anchor = RT_CORNER; // right top corner
717  break;
718 
719  default:
720  Unexpected( CurText() );
721  break;
722  }
723  }
724 }
725 
726 int PAGE_LAYOUT_READER_PARSER::parseInt( int aMin, int aMax )
727 {
728  T token = NextTok();
729 
730  if( token != T_NUMBER )
731  Expecting( T_NUMBER );
732 
733  int val = atoi( CurText() );
734 
735  if( val < aMin )
736  val = aMin;
737  else if( val > aMax )
738  val = aMax;
739 
740  return val;
741 }
742 
743 
745 {
746  T token = NextTok();
747 
748  if( token != T_NUMBER )
749  Expecting( T_NUMBER );
750 
751  double val = strtod( CurText(), NULL );
752 
753  return val;
754 }
755 
756 // defaultPageLayout is the default page layout description
757 // using the S expr.
758 // see page_layout_default_shape.cpp
759 extern const char defaultPageLayout[];
760 
762 {
763  ClearList();
764  PAGE_LAYOUT_READER_PARSER lp_parser( defaultPageLayout, wxT( "default page" ) );
765 
766  try
767  {
768  lp_parser.Parse( this );
769  }
770  catch( const IO_ERROR& ioe )
771  {
772  wxLogMessage( ioe.What() );
773  }
774 }
775 
780 void WORKSHEET_LAYOUT::SetPageLayout( const char* aPageLayout, bool Append )
781 {
782  if( ! Append )
783  ClearList();
784 
785  PAGE_LAYOUT_READER_PARSER lp_parser( aPageLayout, wxT( "Sexpr_string" ) );
786 
787  try
788  {
789  lp_parser.Parse( this );
790  }
791  catch( const IO_ERROR& ioe )
792  {
793  wxLogMessage( ioe.What() );
794  }
795 }
796 
797 #include <wx/file.h>
798 
799 // SetLayout() try to load the aFullFileName custom layout file,
800 // if aFullFileName is empty, try the filename defined by the
801 // environment variable KICAD_WKSFILE (a *.kicad_wks filename).
802 // if does not exists, loads the default page layout.
803 void WORKSHEET_LAYOUT::SetPageLayout( const wxString& aFullFileName, bool Append )
804 {
805  wxString fullFileName = aFullFileName;
806 
807  if( !Append )
808  {
809  if( fullFileName.IsEmpty() )
810  wxGetEnv( wxT( "KICAD_WKSFILE" ), &fullFileName );
811 
812  if( fullFileName.IsEmpty() || !wxFileExists( fullFileName ) )
813  {
814  #if 0
815  if( !fullFileName.IsEmpty() )
816  {
817  wxLogMessage( wxT("Page layout file <%s> not found"),
818  fullFileName.GetData() );
819  }
820  #endif
822  return;
823  }
824  }
825 
826  wxFile wksFile( fullFileName );
827 
828  if( ! wksFile.IsOpened() )
829  {
830  if( !Append )
832  return;
833  }
834 
835  int filelen = wksFile.Length();
836  char * buffer = new char[filelen+10];
837 
838  if( wksFile.Read( buffer, filelen ) != filelen )
839  wxLogMessage( _("The file <%s> was not fully read"),
840  fullFileName.GetData() );
841  else
842  {
843  buffer[filelen]=0;
844 
845  if( ! Append )
846  ClearList();
847 
848  PAGE_LAYOUT_READER_PARSER pl_parser( buffer, fullFileName );
849 
850  try
851  {
852  pl_parser.Parse( this );
853  }
854  catch( const IO_ERROR& ioe )
855  {
856  wxLogMessage( ioe.What() );
857  }
858  }
859 
860  delete[] buffer;
861 }
862 
void parseCoordinate(POINT_COORD &aCoord)
int parseInt(int aMin, int aMax)
Function parseInt parses an integer and constrains it between two values.
Class LOCALE_IO is a class that can be instantiated within a scope in which you are expecting excepti...
Definition: common.h:165
void parseText(WORKSHEET_DATAITEM_TEXT *aItem)
parse a text item starting by "(tbtext" and read parameters.
void SetBoundingBox()
calculate the bounding box of the set polygons
void SetScale(double aScale)
void Unexpected(int aTok)
Function Unexpected throws an IO_ERROR exception with an input file specific error message...
Definition: dsnlexer.cpp:369
const std::string & CurStr()
Function CurStr returns a reference to current token in std::string form.
Definition: dsnlexer.h:488
description of graphic items and texts to build a title block
void readPngdata(WORKSHEET_DATAITEM_BITMAP *aItem)
void AppendCorner(const DPOINT &aCorner)
add a corner in corner list
double parseDouble()
Function parseDouble parses a double.
wxString FromUTF8()
Function FromUTF8 returns the current token text as a wxString, assuming that the input byte stream i...
Definition: dsnlexer.h:498
void SetDefaultLayout()
Fills the list with the default layout shape.
void SetLeftMargin(double aMargin)
void SetTopMargin(double aMargin)
PAGE_LAYOUT_READER_PARSER(const char *aLine, const wxString &aSource)
This class handle bitmap images in KiCad.
void SetBottomMargin(double aMargin)
static double parseDouble(FILE_LINE_READER &aReader, const char *aLine, const char **aOutput=NULL)
Function parseDouble.
void Append(WORKSHEET_DATAITEM *aItem)
Add an item to the list of items.
void SetItalic(bool aState)
Function SetItalic Toggles on/off the italic option flag.
const char defaultPageLayout[]
void parseBitmap(WORKSHEET_DATAITEM_BITMAP *aItem)
parse a bitmap item starting by "( bitmap" and read parameters.
C++ does not put enum values in separate namespaces unless the enum itself is in a separate namespace...
TB_READER_T::T NeedSYMBOLorNUMBER()
Function NeedSYMBOLorNUMBER calls NextTok() and then verifies that the token read in satisfies bool I...
void ClearList()
erase the list of items
TB_READER_T::T NextTok()
Function NextTok returns the next token found in the input file or T_EOF when reaching the end of fil...
Class PAGE_LAYOUT_READER_PARSER holds data and functions pertinent to parsing a S-expression file for...
void Expecting(int aTok)
Function Expecting throws an IO_ERROR exception with an input file specific error message...
Definition: dsnlexer.cpp:353
void parsePolyOutline(WORKSHEET_DATAITEM_POLYPOLYGON *aItem)
parse a list of corners starting by "( pts" and read coordinates.
WORKSHEET_LAYOUT handles the graphic items list to draw/plot the title block and other items (page re...
Class PAGE_LAYOUT_READER_LEXER is an automatically generated class using the TokenList2DnsLexer.cmake technology, based on keywords provided by file: /home/kicad/workspace/kicad-doxygen/common/page_layout/page_layout_reader.keywords.
static double m_DefaultTextThickness
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
void parseGraphic(WORKSHEET_DATAITEM *aItem)
parse a graphic item starting by "(line" or "(rect" and read parameters.
bool LoadData(LINE_READER &aLine, wxString &aErrorMsg)
Load an image data saved by SaveData (png, in Hexadecimal form)
T
enum T contains all this lexer's tokens.
void SetBold(bool aState)
Function SetBold Toggles on/off the bold option flag.
void CloseContour()
Closes the current contour, by storing the index of the last corner of the current polygon in m_polyI...
void NeedRIGHT()
Function NeedRIGHT calls NextTok() and then verifies that the token read in is a DSN_RIGHT.
Definition: dsnlexer.cpp:401
classes and function to generate graphics to plt or draw titles blocks and frame references ...
void Parse(WORKSHEET_LAYOUT *aLayout)
Basic classes for most KiCad items.
void SetPage1Option(int aChoice)
Set the option for page 1.
Class STRING_LINE_READER is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:254
const char * CurText()
Function CurText returns a pointer to the current token's text.
Definition: dsnlexer.h:479
void parsePolygon(WORKSHEET_DATAITEM_POLYPOLYGON *aItem)
parse a polygon item starting by "( polygon" and read parameters.
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 parseSetup(WORKSHEET_LAYOUT *aLayout)
static long parseInt(const wxString &aValue, double aScalar)
Definition: gpcb_plugin.cpp:74
void SetRightMargin(double aMargin)
void SetPageLayout(const wxString &aFullFileName=wxEmptyString, bool Append=false)
Populates the list with a custom layout, or the default layout, if no custom layout available...
void readOption(WORKSHEET_DATAITEM *aItem)