KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drawing_sheet_parser.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2013 Jean-Pierre Charras <jp.charras at wanadoo.fr>.
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <charconv>
23#include <fmt/format.h>
24#include <wx/base64.h>
25#include <wx/ffile.h>
26#include <wx/log.h>
27
28#include <eda_item.h>
29#include <locale_io.h>
30#include <string_utils.h>
34#include <drawing_sheet/drawing_sheet_lexer.h>
36#include <font/font.h>
37
38using namespace DRAWINGSHEET_T;
39
43class DRAWING_SHEET_PARSER : public DRAWING_SHEET_LEXER
44{
45public:
46 DRAWING_SHEET_PARSER( const char* aLine, const wxString& aSource );
47 void Parse( DS_DATA_MODEL* aLayout );
48
49private:
54 void parseHeader( T aHeaderType );
55
59 int parseInt();
60
68 int parseInt( int aMin, int aMax );
69
75 double parseDouble();
76
77 void parseSetup( DS_DATA_MODEL* aLayout );
78
82 void parseGraphic( DS_DATA_ITEM * aItem );
83
87 void parseText( DS_DATA_ITEM_TEXT * aItem );
88
93 void parsePolygon( DS_DATA_ITEM_POLYGONS * aItem );
94
99
100
104 void parseBitmap( DS_DATA_ITEM_BITMAP * aItem );
105
106 void parseCoordinate( POINT_COORD& aCoord);
107 void readOption( DS_DATA_ITEM * aItem );
108 void readPngdata( DS_DATA_ITEM_BITMAP * aItem );
109
110private:
113};
114
115
117 const wxString& aSource ) :
118 DRAWING_SHEET_LEXER( aLine, aSource ),
120{
121}
122
123
124wxString convertLegacyVariableRefs( const wxString& aTextbase )
125{
126 wxString msg;
127
128 /*
129 * Legacy formats
130 * %% = replaced by %
131 * %K = Kicad version
132 * %Z = paper format name (A4, USLetter)
133 * %Y = company name
134 * %D = date
135 * %R = revision
136 * %S = sheet number
137 * %N = number of sheets
138 * %L = layer name
139 * %Cx = comment (x = 0 to 9 to identify the comment)
140 * %F = filename
141 * %P = sheet path (sheet full name)
142 * %T = title
143 */
144
145 for( unsigned ii = 0; ii < aTextbase.Len(); ii++ )
146 {
147 if( aTextbase[ii] != '%' )
148 {
149 msg << aTextbase[ii];
150 continue;
151 }
152
153 if( ++ii >= aTextbase.Len() )
154 break;
155
156 wxChar format = aTextbase[ii];
157
158 switch( format )
159 {
160 case '%': msg += '%'; break;
161 case 'D': msg += wxT( "${ISSUE_DATE}" ); break;
162 case 'R': msg += wxT( "${REVISION}" ); break;
163 case 'K': msg += wxT( "${KICAD_VERSION}" ); break;
164 case 'Z': msg += wxT( "${PAPER}" ); break;
165 case 'S': msg += wxT( "${#}" ); break;
166 case 'N': msg += wxT( "${##}" ); break;
167 case 'F': msg += wxT( "${FILENAME}" ); break;
168 case 'L': msg += wxT( "${LAYER}" ); break;
169 case 'P': msg += wxT( "${SHEETPATH}" ); break;
170 case 'Y': msg += wxT( "${COMPANY}" ); break;
171 case 'T': msg += wxT( "${TITLE}" ); break;
172 case 'C':
173 format = aTextbase[++ii];
174
175 switch( format )
176 {
177 case '0': msg += wxT( "${COMMENT1}" ); break;
178 case '1': msg += wxT( "${COMMENT2}" ); break;
179 case '2': msg += wxT( "${COMMENT3}" ); break;
180 case '3': msg += wxT( "${COMMENT4}" ); break;
181 case '4': msg += wxT( "${COMMENT5}" ); break;
182 case '5': msg += wxT( "${COMMENT6}" ); break;
183 case '6': msg += wxT( "${COMMENT7}" ); break;
184 case '7': msg += wxT( "${COMMENT8}" ); break;
185 case '8': msg += wxT( "${COMMENT9}" ); break;
186 }
187 break;
188
189 default:
190 break;
191 }
192 }
193
194 return msg;
195}
196
197
199{
200 DS_DATA_ITEM* item;
201 LOCALE_IO toggle;
202
203 NeedLEFT();
204 T token = NextTok();
205
206 parseHeader( token );
208
209 auto checkVersion =
210 [&]()
211 {
213 {
214 throw FUTURE_FORMAT_ERROR( fmt::format( "{}", m_requiredVersion ),
216 }
217 };
218
219 for( token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
220 {
221 if( token == T_LEFT )
222 token = NextTok();
223
224 switch( token )
225 {
226 case T_generator:
227 // (generator "genname"); we don't care about it at the moment.
228 NeedSYMBOL();
229 NeedRIGHT();
230 break;
231
232 case T_generator_version:
233 NextTok();
234 m_generatorVersion = FromUTF8();
235 NeedRIGHT();
236 break;
237
238 case T_setup: // Defines default values for graphic items
239 // Check the version here, because the generator and generator_version (if available)
240 // will have been parsed by now given the order the formatter writes them in
241 checkVersion();
242 parseSetup( aLayout );
243 break;
244
245 case T_line:
247 parseGraphic( item );
248 aLayout->Append( item );
249 break;
250
251 case T_rect:
253 parseGraphic( item );
254 aLayout->Append( item );
255 break;
256
257 case T_polygon:
258 item = new DS_DATA_ITEM_POLYGONS();
260 aLayout->Append( item );
261 break;
262
263 case T_bitmap:
264 item = new DS_DATA_ITEM_BITMAP( NULL );
266
267 // Drop invalid bitmaps
268 if( static_cast<DS_DATA_ITEM_BITMAP*>( item )->m_ImageBitmap->GetOriginalImageData() )
269 {
270 aLayout->Append( item );
271 }
272 else
273 {
274 delete static_cast<DS_DATA_ITEM_BITMAP*>( item )->m_ImageBitmap;
275 delete item;
276 }
277
278 break;
279
280 case T_tbtext:
281 NeedSYMBOLorNUMBER();
282 item = new DS_DATA_ITEM_TEXT( convertLegacyVariableRefs( FromUTF8() ) );
283 parseText( (DS_DATA_ITEM_TEXT*) item );
284 aLayout->Append( item );
285 break;
286
287 default:
288 Unexpected( CurText() );
289 break;
290 }
291 }
292}
293
294
296{
297 // The older files had no versioning and their first token after the initial left parenthesis
298 // was a `page_layout` or `drawing_sheet` token. The newer files have versions and have a
299 // `kicad_wks` token instead.
300
301 if( aHeaderType == T_kicad_wks || aHeaderType == T_drawing_sheet )
302 {
303 NeedLEFT();
304
305 T tok = NextTok();
306
307 if( tok == T_version )
308 {
310
311 NeedRIGHT();
312 }
313 else
314 {
315 Expecting( T_version );
316 }
317 }
318 else
319 {
320 // We assign version 0 to files that were created before there was any versioning of
321 // worksheets. The below line is not strictly necessary, as `m_requiredVersion` is already
322 // initialized to 0 in the constructor.
324 }
325}
326
327
329{
330 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
331 {
332 switch( token )
333 {
334 case T_LEFT:
335 break;
336
337 case T_linewidth:
338 aLayout->m_DefaultLineWidth = parseDouble();
339 NeedRIGHT();
340 break;
341
342 case T_textsize:
343 aLayout->m_DefaultTextSize.x = parseDouble();
344 aLayout->m_DefaultTextSize.y = parseDouble();
345 NeedRIGHT();
346 break;
347
348 case T_textlinewidth:
350 NeedRIGHT();
351 break;
352
353 case T_left_margin:
354 aLayout->SetLeftMargin( parseDouble() );
355 NeedRIGHT();
356 break;
357
358 case T_right_margin:
359 aLayout->SetRightMargin( parseDouble() );
360 NeedRIGHT();
361 break;
362
363 case T_top_margin:
364 aLayout->SetTopMargin( parseDouble() );
365 NeedRIGHT();
366 break;
367
368 case T_bottom_margin:
369 aLayout->SetBottomMargin( parseDouble() );
370 NeedRIGHT();
371 break;
372
373 default:
374 Unexpected( CurText() );
375 break;
376 }
377 }
378
379 // The file is well-formed. If it has no further items, then that's the way the
380 // user wants it.
381 aLayout->AllowVoidList( true );
382}
383
384
386{
387 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
388 {
389 if( token == T_LEFT )
390 token = NextTok();
391
392 switch( token )
393 {
394 case T_comment:
395 NeedSYMBOLorNUMBER();
396 aItem->m_Info = FromUTF8();
397 NeedRIGHT();
398 break;
399
400 case T_pos:
401 parseCoordinate( aItem->m_Pos );
402 break;
403
404 case T_name:
405 NeedSYMBOLorNUMBER();
406 aItem->m_Name = FromUTF8();
407 NeedRIGHT();
408 break;
409
410 case T_option:
411 readOption( aItem );
412 break;
413
414 case T_pts:
415 parsePolyOutline( aItem );
416 aItem->CloseContour();
417 break;
418
419 case T_rotate:
421 NeedRIGHT();
422 break;
423
424 case T_repeat:
425 aItem->m_RepeatCount = parseInt( 1, 100 );
426 NeedRIGHT();
427 break;
428
429 case T_incrx:
431 NeedRIGHT();
432 break;
433
434 case T_incry:
436 NeedRIGHT();
437 break;
438
439 case T_linewidth:
440 aItem->m_LineWidth = parseDouble();
441 NeedRIGHT();
442 break;
443
444 default:
445 Unexpected( CurText() );
446 break;
447 }
448 }
449
450 aItem->SetBoundingBox();
451}
452
453
455{
456 VECTOR2D corner;
457
458 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
459 {
460 if( token == T_LEFT )
461 token = NextTok();
462
463 switch( token )
464 {
465 case T_xy:
466 corner.x = parseDouble();
467 corner.y = parseDouble();
468 aItem->AppendCorner( corner );
469 NeedRIGHT();
470 break;
471
472 default:
473 Unexpected( CurText() );
474 break;
475 }
476 }
477}
478
479
481{
483 aItem->m_ImageBitmap = image;
484
485 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
486 {
487 if( token == T_LEFT )
488 token = NextTok();
489
490 switch( token )
491 {
492 case T_name:
493 NeedSYMBOLorNUMBER();
494 aItem->m_Name = FromUTF8();
495 NeedRIGHT();
496 break;
497
498 case T_pos:
499 parseCoordinate( aItem->m_Pos );
500 break;
501
502 case T_repeat:
503 aItem->m_RepeatCount = parseInt( 1, 100 );
504 NeedRIGHT();
505 break;
506
507 case T_incrx:
509 NeedRIGHT();
510 break;
511
512 case T_incry:
514 NeedRIGHT();
515 break;
516
517 case T_linewidth:
518 aItem->m_LineWidth = parseDouble();
519 NeedRIGHT();
520 break;
521
522 case T_scale:
524 NeedRIGHT();
525 break;
526
527 case T_comment:
528 NeedSYMBOLorNUMBER();
529 aItem->m_Info = FromUTF8();
530 NeedRIGHT();
531 break;
532
533 case T_data:
534 {
535 token = NextTok();
536
537 wxString data;
538
539 // Reserve 512K because most image files are going to be larger than the default
540 // 1K that wxString reserves.
541 data.reserve( 1 << 19 );
542
543 while( token != T_RIGHT )
544 {
545 if( !IsSymbol( token ) )
546 Expecting( "base64 image data" );
547
548 data += FromUTF8();
549 token = NextTok();
550 }
551
552 wxMemoryBuffer buffer = wxBase64Decode( data );
553
554 if( !aItem->m_ImageBitmap->ReadImageFile( buffer ) )
555 THROW_IO_ERROR( _( "Failed to read image data." ) );
556
557 break;
558 }
559
560 case T_pngdata:
561 readPngdata( aItem );
562 break;
563
564 case T_option:
565 readOption( aItem );
566 break;
567
568 default:
569 Unexpected( CurText() );
570 break;
571 }
572 }
573}
574
575
577{
578 std::string tmp;
579
580 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
581 {
582 if( token == T_LEFT )
583 token = NextTok();
584
585 switch( token )
586 {
587 case T_data:
588 NeedSYMBOLorNUMBER();
589 tmp += CurStr();
590 tmp += "\n";
591 NeedRIGHT();
592 break;
593
594 default:
595 Unexpected( CurText() );
596 break;
597 }
598 }
599
600 tmp += "EndData";
601
602 wxString msg;
603 STRING_LINE_READER str_reader( tmp, wxT("Png kicad_wks data") );
604
605 aItem->m_ImageBitmap->LoadLegacyData( str_reader, msg );
606}
607
608
610{
611 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
612 {
613 switch( token )
614 {
615 case T_page1only: aItem->SetPage1Option( FIRST_PAGE_ONLY ); break;
616 case T_notonpage1: aItem->SetPage1Option( SUBSEQUENT_PAGES ); break;
617 default: Unexpected( CurText() ); break;
618 }
619 }
620}
621
622
624{
625 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
626 {
627 if( token == T_LEFT )
628 {
629 token = NextTok();
630 }
631 else
632 {
633 // If another token than T_LEFT is read here, this is an error
634 // however, due to a old bug in kicad, the token T_end can be found
635 // without T_LEFT in a very few .wks files (perhaps only one in a demo).
636 // So this ugly hack disables the error detection.
637 if( token != T_end )
638 Unexpected( CurText() );
639 }
640
641 switch( token )
642 {
643 case T_comment:
644 NeedSYMBOLorNUMBER();
645 aItem->m_Info = FromUTF8();
646 NeedRIGHT();
647 break;
648
649 case T_option:
650 readOption( aItem );
651 break;
652
653 case T_name:
654 NeedSYMBOLorNUMBER();
655 aItem->m_Name = FromUTF8();
656 NeedRIGHT();
657 break;
658
659 case T_start:
660 parseCoordinate( aItem->m_Pos );
661 break;
662
663 case T_end:
664 parseCoordinate( aItem->m_End );
665 break;
666
667 case T_repeat:
668 aItem->m_RepeatCount = parseInt( 1, 100 );
669 NeedRIGHT();
670 break;
671
672 case T_incrx:
674 NeedRIGHT();
675 break;
676
677 case T_incry:
679 NeedRIGHT();
680 break;
681
682 case T_linewidth:
683 aItem->m_LineWidth = parseDouble();
684 NeedRIGHT();
685 break;
686
687 default:
688 Unexpected( CurText() );
689 break;
690 }
691 }
692}
693
694
696{
697 if( m_requiredVersion < 20210606 )
699
700 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
701 {
702 if( token == T_LEFT )
703 token = NextTok();
704
705 switch( token )
706 {
707 case T_comment:
708 NeedSYMBOLorNUMBER();
709 aItem->m_Info = FromUTF8();
710 NeedRIGHT();
711 break;
712
713 case T_option:
714 readOption( aItem );
715 break;
716
717 case T_name:
718 NeedSYMBOLorNUMBER();
719 aItem->m_Name = FromUTF8();
720 NeedRIGHT();
721 break;
722
723 case T_pos:
724 parseCoordinate( aItem->m_Pos );
725 break;
726
727 case T_repeat:
728 aItem->m_RepeatCount = parseInt( 1, 100 );
729 NeedRIGHT();
730 break;
731
732 case T_incrx:
734 NeedRIGHT();
735 break;
736
737 case T_incry:
739 NeedRIGHT();
740 break;
741
742 case T_incrlabel:
743 aItem->m_IncrementLabel = parseInt(INT_MIN, INT_MAX);
744 NeedRIGHT();
745 break;
746
747 case T_maxlen:
749 NeedRIGHT();
750 break;
751
752 case T_maxheight:
754 NeedRIGHT();
755 break;
756
757 case T_font:
758 {
759 wxString faceName;
760
762
763 for( token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
764 {
765 switch( token )
766 {
767 case T_LEFT:
768 break;
769
770 case T_face:
771 NeedSYMBOL();
772 faceName = FromUTF8();
773 NeedRIGHT();
774 break;
775
776 case T_bold:
777 aItem->m_Bold = true;
778 break;
779
780 case T_italic:
781 aItem->m_Italic = true;
782 break;
783
784 case T_size:
785 aItem->m_TextSize.x = parseDouble();
786 aItem->m_TextSize.y = parseDouble();
787 NeedRIGHT();
788 break;
789
790 case T_color:
791 aItem->m_TextColor.r = parseInt( 0, 255 ) / 255.0;
792 aItem->m_TextColor.g = parseInt( 0, 255 ) / 255.0;
793 aItem->m_TextColor.b = parseInt( 0, 255 ) / 255.0;
794 aItem->m_TextColor.a = std::clamp( parseDouble(), 0.0, 1.0 );
795 NeedRIGHT();
796 break;
797
798 case T_linewidth:
799 aItem->m_LineWidth = parseDouble();
800 NeedRIGHT();
801 break;
802
803 default:
804 Unexpected( CurText() );
805 break;
806 }
807 }
808
809 if( !faceName.IsEmpty() )
810 aItem->m_Font = KIFONT::FONT::GetFont( faceName, aItem->m_Bold, aItem->m_Italic );
811
812 break;
813 }
814
815 case T_justify:
816 for( token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
817 {
818 switch( token )
819 {
820 case T_center:
823 break;
824
825 case T_left:
827 break;
828
829 case T_right:
831 break;
832
833 case T_top:
835 break;
836
837 case T_bottom:
839 break;
840
841 default:
842 Unexpected( CurText() );
843 break;
844 }
845 }
846 break;
847
848 case T_rotate:
849 aItem->m_Orient = parseDouble();
850 NeedRIGHT();
851 break;
852
853 default:
854 Unexpected( CurText() );
855 break;
856 }
857 }
858}
859
860
862{
863 aCoord.m_Pos.x = parseDouble();
864 aCoord.m_Pos.y = parseDouble();
865
866 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
867 {
868 switch( token )
869 {
870 case T_ltcorner: aCoord.m_Anchor = LT_CORNER; break;
871 case T_lbcorner: aCoord.m_Anchor = LB_CORNER; break;
872 case T_rbcorner: aCoord.m_Anchor = RB_CORNER; break;
873 case T_rtcorner: aCoord.m_Anchor = RT_CORNER; break;
874 default: Unexpected( CurText() ); break;
875 }
876 }
877}
878
879
881{
882 T token = NextTok();
883
884 if( token != T_NUMBER )
885 Expecting( T_NUMBER );
886
887 return atoi( CurText() );
888}
889
890
891int DRAWING_SHEET_PARSER::parseInt( int aMin, int aMax )
892{
893 int val = parseInt();
894
895 if( val < aMin )
896 val = aMin;
897 else if( val > aMax )
898 val = aMax;
899
900 return val;
901}
902
903
905{
906 T token = NextTok();
907
908 if( token != T_NUMBER )
909 Expecting( T_NUMBER );
910
911
912 return DSNLEXER::parseDouble();
913}
914
915
916// defaultDrawingSheet is the default drawing sheet using the S expr.
917extern const char defaultDrawingSheet[];
918
919
921{
922 SetPageLayout( defaultDrawingSheet, false, wxT( "default page" ) );
923}
924
925
927{
928 return wxString( defaultDrawingSheet );
929}
930
931
932// emptyDrawingSheet is a "empty" drawing sheet using the S expr.
933// there is a 0 length line to fool something somewhere.
934extern const char emptyDrawingSheet[];
935
936
938{
939 SetPageLayout( emptyDrawingSheet, false, wxT( "empty page" ) );
940}
941
942
944{
945 return wxString( emptyDrawingSheet );
946}
947
948
949void DS_DATA_MODEL::SetPageLayout( const char* aPageLayout, bool Append, const wxString& aSource )
950{
951 if( ! Append )
952 ClearList();
953
954 DRAWING_SHEET_PARSER parser( aPageLayout, wxT( "Sexpr_string" ) );
955
956 try
957 {
958 parser.Parse( this );
959 }
960 catch( ... )
961 {
962 // best efforts
963 }
964}
965
966
967bool DS_DATA_MODEL::LoadDrawingSheet( const wxString& aFullFileName, wxString* aMsg, bool aAppend )
968{
969 if( !aAppend )
970 {
971 if( aFullFileName.IsEmpty() )
972 {
974 return true; // we assume its fine / default init
975 }
976
977 if( !wxFileExists( aFullFileName ) )
978 {
979 if( aMsg )
980 *aMsg = _( "File not found." );
981
983 return false;
984 }
985 }
986
987 wxFFile wksFile( aFullFileName, wxS( "rb" ) );
988
989 if( ! wksFile.IsOpened() )
990 {
991 if( aMsg )
992 *aMsg = _( "File could not be opened." );
993
994 if( !aAppend )
996
997 return false;
998 }
999
1000 size_t filelen = wksFile.Length();
1001 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(filelen+10);
1002
1003 if( wksFile.Read( buffer.get(), filelen ) != filelen )
1004 {
1005 if( aMsg )
1006 *aMsg = _( "Drawing sheet was not fully read." );
1007
1008 return false;
1009 }
1010 else
1011 {
1012 buffer[filelen]=0;
1013
1014 if( ! aAppend )
1015 ClearList();
1016
1017 DRAWING_SHEET_PARSER parser( buffer.get(), aFullFileName );
1018
1019 try
1020 {
1021 parser.Parse( this );
1022 }
1023 catch( const IO_ERROR& ioe )
1024 {
1025 if( aMsg )
1026 *aMsg = ioe.What();
1027
1028 return false;
1029 }
1030 catch( const std::bad_alloc& )
1031 {
1032 if( aMsg )
1033 *aMsg = _( "Ran out of memory." );
1034
1035 return false;
1036 }
1037 }
1038
1039 return true;
1040}
This class handle bitmap images in KiCad.
Definition bitmap_base.h:45
bool LoadLegacyData(LINE_READER &aLine, wxString &aErrorMsg)
Load an image data saved by #SaveData.
bool ReadImageFile(const wxString &aFullFilename)
Reads and stores in memory an image file.
void SetScale(double aScale)
Definition bitmap_base.h:70
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:398
Hold data and functions pertinent to parsing a S-expression file for a DS_DATA_MODEL.
void parseCoordinate(POINT_COORD &aCoord)
void parseHeader(T aHeaderType)
Parse the data specified at the very beginning of the file, like version and the application used to ...
DRAWING_SHEET_PARSER(const char *aLine, const wxString &aSource)
void parseBitmap(DS_DATA_ITEM_BITMAP *aItem)
Parse a bitmap item starting by "( bitmap" and read parameters.
void readPngdata(DS_DATA_ITEM_BITMAP *aItem)
void parsePolygon(DS_DATA_ITEM_POLYGONS *aItem)
Parse a polygon item starting by "( polygon" and read parameters.
void parseText(DS_DATA_ITEM_TEXT *aItem)
Parse a text item starting by "(tbtext" and read parameters.
void Parse(DS_DATA_MODEL *aLayout)
int parseInt()
Parse an integer.
void readOption(DS_DATA_ITEM *aItem)
double parseDouble()
Parse a double.
void parseSetup(DS_DATA_MODEL *aLayout)
void parseGraphic(DS_DATA_ITEM *aItem)
Parse a graphic item starting by "(line" or "(rect" and read parameters.
void parsePolyOutline(DS_DATA_ITEM_POLYGONS *aItem)
Parse a list of corners starting by "( pts" and read coordinates.
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
Definition dsnlexer.cpp:860
BITMAP_BASE * m_ImageBitmap
void SetBoundingBox()
Calculate the bounding box of the set polygons.
void CloseContour()
Close the current contour, by storing the index of the last corner of the current polygon in m_polyIn...
void AppendCorner(const VECTOR2D &aCorner)
Add a corner in corner list.
KIFONT::FONT * m_Font
GR_TEXT_H_ALIGN_T m_Hjustify
KIGFX::COLOR4D m_TextColor
VECTOR2D m_BoundingBoxSize
GR_TEXT_V_ALIGN_T m_Vjustify
Drawing sheet structure type definitions.
void SetPage1Option(PAGE_OPTION aChoice)
wxString m_Name
VECTOR2D m_IncrementVector
POINT_COORD m_Pos
wxString m_Info
double m_LineWidth
POINT_COORD m_End
Handle the graphic items list to draw/plot the frame and title block.
bool LoadDrawingSheet(const wxString &aFullFileName, wxString *aMsg, bool aAppend=false)
Populate the list with a custom layout or the default layout if no custom layout is available.
void SetBottomMargin(double aMargin)
VECTOR2D m_DefaultTextSize
void SetRightMargin(double aMargin)
double m_DefaultLineWidth
static wxString DefaultLayout()
Return a string containing the empty layout shape.
static wxString EmptyLayout()
Return a string containing the empty layout shape.
void SetLeftMargin(double aMargin)
double m_DefaultTextThickness
void Append(DS_DATA_ITEM *aItem)
void AllowVoidList(bool Allow)
In KiCad applications, a drawing sheet is needed So if the list is empty, a default drawing sheet is ...
void ClearList()
Erase the list of items.
void SetTopMargin(double aMargin)
void SetFileFormatVersionAtLoad(int aVersion)
void SetPageLayout(const char *aPageLayout, bool aAppend=false, const wxString &aSource=wxT("Sexpr_string"))
Populate the list from a S expr description stored in a string.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:143
double r
Red component.
Definition color4d.h:389
double g
Green component.
Definition color4d.h:390
double a
Alpha component.
Definition color4d.h:392
double b
Blue component.
Definition color4d.h:391
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
A coordinate point.
VECTOR2D m_Pos
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:222
const char emptyDrawingSheet[]
const char defaultDrawingSheet[]
wxString convertLegacyVariableRefs(const wxString &aTextbase)
@ FIRST_PAGE_ONLY
@ SUBSEQUENT_PAGES
@ RB_CORNER
@ RT_CORNER
@ LT_CORNER
@ LB_CORNER
#define SEXPR_WORKSHEET_FILE_VERSION
This file contains the file format version information for the s-expression drawing sheet file format...
#define _(s)
@ DEGREES_T
Definition eda_angle.h:31
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
VECTOR2< double > VECTOR2D
Definition vector2d.h:682