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 <filename_resolver.h>
30#include <locale_io.h>
31#include <pgm_base.h>
32#include <string_utils.h>
36#include <drawing_sheet/drawing_sheet_lexer.h>
38#include <font/font.h>
39
40using namespace DRAWINGSHEET_T;
41
45class DRAWING_SHEET_PARSER : public DRAWING_SHEET_LEXER
46{
47public:
48 DRAWING_SHEET_PARSER( const char* aLine, const wxString& aSource );
49 void Parse( DS_DATA_MODEL* aLayout );
50
51private:
56 void parseHeader( T aHeaderType );
57
61 int parseInt();
62
70 int parseInt( int aMin, int aMax );
71
77 double parseDouble();
78
79 void parseSetup( DS_DATA_MODEL* aLayout );
80
84 void parseGraphic( DS_DATA_ITEM * aItem );
85
89 void parseText( DS_DATA_ITEM_TEXT * aItem );
90
95 void parsePolygon( DS_DATA_ITEM_POLYGONS * aItem );
96
101
102
106 void parseBitmap( DS_DATA_ITEM_BITMAP * aItem );
107
108 void parseCoordinate( POINT_COORD& aCoord);
109 void readOption( DS_DATA_ITEM * aItem );
110 void readPngdata( DS_DATA_ITEM_BITMAP * aItem );
111
112private:
115};
116
117
119 const wxString& aSource ) :
120 DRAWING_SHEET_LEXER( aLine, aSource ),
122{
123}
124
125
126wxString convertLegacyVariableRefs( const wxString& aTextbase )
127{
128 wxString msg;
129
130 /*
131 * Legacy formats
132 * %% = replaced by %
133 * %K = Kicad version
134 * %Z = paper format name (A4, USLetter)
135 * %Y = company name
136 * %D = date
137 * %R = revision
138 * %S = sheet number
139 * %N = number of sheets
140 * %L = layer name
141 * %Cx = comment (x = 0 to 9 to identify the comment)
142 * %F = filename
143 * %P = sheet path (sheet full name)
144 * %T = title
145 */
146
147 for( unsigned ii = 0; ii < aTextbase.Len(); ii++ )
148 {
149 if( aTextbase[ii] != '%' )
150 {
151 msg << aTextbase[ii];
152 continue;
153 }
154
155 if( ++ii >= aTextbase.Len() )
156 break;
157
158 wxChar format = aTextbase[ii];
159
160 switch( format )
161 {
162 case '%': msg += '%'; break;
163 case 'D': msg += wxT( "${ISSUE_DATE}" ); break;
164 case 'R': msg += wxT( "${REVISION}" ); break;
165 case 'K': msg += wxT( "${KICAD_VERSION}" ); break;
166 case 'Z': msg += wxT( "${PAPER}" ); break;
167 case 'S': msg += wxT( "${#}" ); break;
168 case 'N': msg += wxT( "${##}" ); break;
169 case 'F': msg += wxT( "${FILENAME}" ); break;
170 case 'L': msg += wxT( "${LAYER}" ); break;
171 case 'P': msg += wxT( "${SHEETPATH}" ); break;
172 case 'Y': msg += wxT( "${COMPANY}" ); break;
173 case 'T': msg += wxT( "${TITLE}" ); break;
174 case 'C':
175 format = aTextbase[++ii];
176
177 switch( format )
178 {
179 case '0': msg += wxT( "${COMMENT1}" ); break;
180 case '1': msg += wxT( "${COMMENT2}" ); break;
181 case '2': msg += wxT( "${COMMENT3}" ); break;
182 case '3': msg += wxT( "${COMMENT4}" ); break;
183 case '4': msg += wxT( "${COMMENT5}" ); break;
184 case '5': msg += wxT( "${COMMENT6}" ); break;
185 case '6': msg += wxT( "${COMMENT7}" ); break;
186 case '7': msg += wxT( "${COMMENT8}" ); break;
187 case '8': msg += wxT( "${COMMENT9}" ); break;
188 }
189 break;
190
191 default:
192 break;
193 }
194 }
195
196 return msg;
197}
198
199
201{
202 DS_DATA_ITEM* item;
203 LOCALE_IO toggle;
204
205 NeedLEFT();
206 T token = NextTok();
207
208 parseHeader( token );
210
211 // Sheets predating the generator token, or a reused model, must not inherit a stale generator.
212 aLayout->SetGenerator( wxT( "pl_editor" ) );
213
214 auto checkVersion =
215 [&]()
216 {
218 {
219 throw FUTURE_FORMAT_ERROR( fmt::format( "{}", m_requiredVersion ),
221 }
222 };
223
224 for( token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
225 {
226 if( token == T_LEFT )
227 token = NextTok();
228
229 switch( token )
230 {
231 case T_generator:
232 NeedSYMBOL();
233 aLayout->SetGenerator( FromUTF8() );
234 NeedRIGHT();
235 break;
236
237 case T_generator_version:
238 NextTok();
239 m_generatorVersion = FromUTF8();
240 NeedRIGHT();
241 break;
242
243 case T_setup: // Defines default values for graphic items
244 // Check the version here, because the generator and generator_version (if available)
245 // will have been parsed by now given the order the formatter writes them in
246 checkVersion();
247 parseSetup( aLayout );
248 break;
249
250 case T_line:
252 parseGraphic( item );
253 aLayout->Append( item );
254 break;
255
256 case T_rect:
258 parseGraphic( item );
259 aLayout->Append( item );
260 break;
261
262 case T_polygon:
263 item = new DS_DATA_ITEM_POLYGONS();
265 aLayout->Append( item );
266 break;
267
268 case T_bitmap:
269 item = new DS_DATA_ITEM_BITMAP( NULL );
271
272 // Drop invalid bitmaps
273 if( static_cast<DS_DATA_ITEM_BITMAP*>( item )->m_ImageBitmap->GetOriginalImageData() )
274 {
275 aLayout->Append( item );
276 }
277 else
278 {
279 delete static_cast<DS_DATA_ITEM_BITMAP*>( item )->m_ImageBitmap;
280 delete item;
281 }
282
283 break;
284
285 case T_tbtext:
286 NeedSYMBOLorNUMBER();
287 item = new DS_DATA_ITEM_TEXT( convertLegacyVariableRefs( FromUTF8() ) );
288 parseText( (DS_DATA_ITEM_TEXT*) item );
289 aLayout->Append( item );
290 break;
291
292 default:
293 Unexpected( CurText() );
294 break;
295 }
296 }
297}
298
299
301{
302 // The older files had no versioning and their first token after the initial left parenthesis
303 // was a `page_layout` or `drawing_sheet` token. The newer files have versions and have a
304 // `kicad_wks` token instead.
305
306 if( aHeaderType == T_kicad_wks || aHeaderType == T_drawing_sheet )
307 {
308 NeedLEFT();
309
310 T tok = NextTok();
311
312 if( tok == T_version )
313 {
315
316 NeedRIGHT();
317 }
318 else
319 {
320 Expecting( T_version );
321 }
322 }
323 else
324 {
325 // We assign version 0 to files that were created before there was any versioning of
326 // worksheets. The below line is not strictly necessary, as `m_requiredVersion` is already
327 // initialized to 0 in the constructor.
329 }
330}
331
332
334{
335 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
336 {
337 switch( token )
338 {
339 case T_LEFT:
340 break;
341
342 case T_linewidth:
343 aLayout->m_DefaultLineWidth = parseDouble();
344 NeedRIGHT();
345 break;
346
347 case T_textsize:
348 aLayout->m_DefaultTextSize.x = parseDouble();
349 aLayout->m_DefaultTextSize.y = parseDouble();
350 NeedRIGHT();
351 break;
352
353 case T_textlinewidth:
355 NeedRIGHT();
356 break;
357
358 case T_left_margin:
359 aLayout->SetLeftMargin( parseDouble() );
360 NeedRIGHT();
361 break;
362
363 case T_right_margin:
364 aLayout->SetRightMargin( parseDouble() );
365 NeedRIGHT();
366 break;
367
368 case T_top_margin:
369 aLayout->SetTopMargin( parseDouble() );
370 NeedRIGHT();
371 break;
372
373 case T_bottom_margin:
374 aLayout->SetBottomMargin( parseDouble() );
375 NeedRIGHT();
376 break;
377
378 default:
379 Unexpected( CurText() );
380 break;
381 }
382 }
383
384 // The file is well-formed. If it has no further items, then that's the way the
385 // user wants it.
386 aLayout->AllowVoidList( true );
387}
388
389
391{
392 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
393 {
394 if( token == T_LEFT )
395 token = NextTok();
396
397 switch( token )
398 {
399 case T_comment:
400 NeedSYMBOLorNUMBER();
401 aItem->m_Info = FromUTF8();
402 NeedRIGHT();
403 break;
404
405 case T_pos:
406 parseCoordinate( aItem->m_Pos );
407 break;
408
409 case T_name:
410 NeedSYMBOLorNUMBER();
411 aItem->m_Name = FromUTF8();
412 NeedRIGHT();
413 break;
414
415 case T_option:
416 readOption( aItem );
417 break;
418
419 case T_pts:
420 parsePolyOutline( aItem );
421 aItem->CloseContour();
422 break;
423
424 case T_rotate:
426 NeedRIGHT();
427 break;
428
429 case T_repeat:
431 NeedRIGHT();
432 break;
433
434 case T_incrx:
436 NeedRIGHT();
437 break;
438
439 case T_incry:
441 NeedRIGHT();
442 break;
443
444 case T_linewidth:
445 aItem->m_LineWidth = parseDouble();
446 NeedRIGHT();
447 break;
448
449 default:
450 Unexpected( CurText() );
451 break;
452 }
453 }
454
455 aItem->SetBoundingBox();
456}
457
458
460{
461 VECTOR2D corner;
462
463 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
464 {
465 if( token == T_LEFT )
466 token = NextTok();
467
468 switch( token )
469 {
470 case T_xy:
471 corner.x = parseDouble();
472 corner.y = parseDouble();
473 aItem->AppendCorner( corner );
474 NeedRIGHT();
475 break;
476
477 default:
478 Unexpected( CurText() );
479 break;
480 }
481 }
482}
483
484
486{
488 aItem->m_ImageBitmap = image;
489
490 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
491 {
492 if( token == T_LEFT )
493 token = NextTok();
494
495 switch( token )
496 {
497 case T_name:
498 NeedSYMBOLorNUMBER();
499 aItem->m_Name = FromUTF8();
500 NeedRIGHT();
501 break;
502
503 case T_pos:
504 parseCoordinate( aItem->m_Pos );
505 break;
506
507 case T_repeat:
509 NeedRIGHT();
510 break;
511
512 case T_incrx:
514 NeedRIGHT();
515 break;
516
517 case T_incry:
519 NeedRIGHT();
520 break;
521
522 case T_linewidth:
523 aItem->m_LineWidth = parseDouble();
524 NeedRIGHT();
525 break;
526
527 case T_scale:
529 NeedRIGHT();
530 break;
531
532 case T_comment:
533 NeedSYMBOLorNUMBER();
534 aItem->m_Info = FromUTF8();
535 NeedRIGHT();
536 break;
537
538 case T_data:
539 {
540 token = NextTok();
541
542 wxString data;
543
544 // Reserve 512K because most image files are going to be larger than the default
545 // 1K that wxString reserves.
546 data.reserve( 1 << 19 );
547
548 while( token != T_RIGHT )
549 {
550 if( !IsSymbol( token ) )
551 Expecting( "base64 image data" );
552
553 data += FromUTF8();
554 token = NextTok();
555 }
556
557 wxMemoryBuffer buffer = wxBase64Decode( data );
558
559 if( !aItem->m_ImageBitmap->ReadImageFile( buffer ) )
560 THROW_IO_ERROR( _( "Failed to read image data." ) );
561
562 break;
563 }
564
565 case T_pngdata:
566 readPngdata( aItem );
567 break;
568
569 case T_option:
570 readOption( aItem );
571 break;
572
573 default:
574 Unexpected( CurText() );
575 break;
576 }
577 }
578}
579
580
582{
583 std::string tmp;
584
585 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
586 {
587 if( token == T_LEFT )
588 token = NextTok();
589
590 switch( token )
591 {
592 case T_data:
593 NeedSYMBOLorNUMBER();
594 tmp += CurStr();
595 tmp += "\n";
596 NeedRIGHT();
597 break;
598
599 default:
600 Unexpected( CurText() );
601 break;
602 }
603 }
604
605 tmp += "EndData";
606
607 wxString msg;
608 STRING_LINE_READER str_reader( tmp, wxT("Png kicad_wks data") );
609
610 aItem->m_ImageBitmap->LoadLegacyData( str_reader, msg );
611}
612
613
615{
616 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
617 {
618 switch( token )
619 {
620 case T_page1only: aItem->SetPage1Option( FIRST_PAGE_ONLY ); break;
621 case T_notonpage1: aItem->SetPage1Option( SUBSEQUENT_PAGES ); break;
622 default: Unexpected( CurText() ); break;
623 }
624 }
625}
626
627
629{
630 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
631 {
632 if( token == T_LEFT )
633 {
634 token = NextTok();
635 }
636 else
637 {
638 // If another token than T_LEFT is read here, this is an error
639 // however, due to a old bug in kicad, the token T_end can be found
640 // without T_LEFT in a very few .wks files (perhaps only one in a demo).
641 // So this ugly hack disables the error detection.
642 if( token != T_end )
643 Unexpected( CurText() );
644 }
645
646 switch( token )
647 {
648 case T_comment:
649 NeedSYMBOLorNUMBER();
650 aItem->m_Info = FromUTF8();
651 NeedRIGHT();
652 break;
653
654 case T_option:
655 readOption( aItem );
656 break;
657
658 case T_name:
659 NeedSYMBOLorNUMBER();
660 aItem->m_Name = FromUTF8();
661 NeedRIGHT();
662 break;
663
664 case T_start:
665 parseCoordinate( aItem->m_Pos );
666 break;
667
668 case T_end:
669 parseCoordinate( aItem->m_End );
670 break;
671
672 case T_repeat:
674 NeedRIGHT();
675 break;
676
677 case T_incrx:
679 NeedRIGHT();
680 break;
681
682 case T_incry:
684 NeedRIGHT();
685 break;
686
687 case T_linewidth:
688 aItem->m_LineWidth = parseDouble();
689 NeedRIGHT();
690 break;
691
692 default:
693 Unexpected( CurText() );
694 break;
695 }
696 }
697}
698
699
701{
702 if( m_requiredVersion < 20210606 )
704
705 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
706 {
707 if( token == T_LEFT )
708 token = NextTok();
709
710 switch( token )
711 {
712 case T_comment:
713 NeedSYMBOLorNUMBER();
714 aItem->m_Info = FromUTF8();
715 NeedRIGHT();
716 break;
717
718 case T_option:
719 readOption( aItem );
720 break;
721
722 case T_name:
723 NeedSYMBOLorNUMBER();
724 aItem->m_Name = FromUTF8();
725 NeedRIGHT();
726 break;
727
728 case T_pos:
729 parseCoordinate( aItem->m_Pos );
730 break;
731
732 case T_repeat:
734 NeedRIGHT();
735 break;
736
737 case T_incrx:
739 NeedRIGHT();
740 break;
741
742 case T_incry:
744 NeedRIGHT();
745 break;
746
747 case T_incrlabel:
748 aItem->m_IncrementLabel = parseInt(INT_MIN, INT_MAX);
749 NeedRIGHT();
750 break;
751
752 case T_maxlen:
754 NeedRIGHT();
755 break;
756
757 case T_maxheight:
759 NeedRIGHT();
760 break;
761
762 case T_font:
763 {
764 wxString faceName;
765
767
768 for( token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
769 {
770 switch( token )
771 {
772 case T_LEFT:
773 break;
774
775 case T_face:
776 NeedSYMBOL();
777 faceName = FromUTF8();
778 NeedRIGHT();
779 break;
780
781 case T_bold:
782 aItem->m_Bold = true;
783 break;
784
785 case T_italic:
786 aItem->m_Italic = true;
787 break;
788
789 case T_size:
790 aItem->m_TextSize.x = parseDouble();
791 aItem->m_TextSize.y = parseDouble();
792 NeedRIGHT();
793 break;
794
795 case T_color:
796 aItem->m_TextColor.r = parseInt( 0, 255 ) / 255.0;
797 aItem->m_TextColor.g = parseInt( 0, 255 ) / 255.0;
798 aItem->m_TextColor.b = parseInt( 0, 255 ) / 255.0;
799 aItem->m_TextColor.a = std::clamp( parseDouble(), 0.0, 1.0 );
800 NeedRIGHT();
801 break;
802
803 case T_linewidth:
804 aItem->m_LineWidth = parseDouble();
805 NeedRIGHT();
806 break;
807
808 default:
809 Unexpected( CurText() );
810 break;
811 }
812 }
813
814 if( !faceName.IsEmpty() )
815 aItem->m_Font = KIFONT::FONT::GetFont( faceName, aItem->m_Bold, aItem->m_Italic );
816
817 break;
818 }
819
820 case T_justify:
821 for( token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
822 {
823 switch( token )
824 {
825 case T_center:
828 break;
829
830 case T_left:
832 break;
833
834 case T_right:
836 break;
837
838 case T_top:
840 break;
841
842 case T_bottom:
844 break;
845
846 default:
847 Unexpected( CurText() );
848 break;
849 }
850 }
851 break;
852
853 case T_rotate:
854 aItem->m_Orient = parseDouble();
855 NeedRIGHT();
856 break;
857
858 default:
859 Unexpected( CurText() );
860 break;
861 }
862 }
863}
864
865
867{
868 aCoord.m_Pos.x = parseDouble();
869 aCoord.m_Pos.y = parseDouble();
870
871 for( T token = NextTok(); token != T_RIGHT && token != EOF; token = NextTok() )
872 {
873 switch( token )
874 {
875 case T_ltcorner: aCoord.m_Anchor = LT_CORNER; break;
876 case T_lbcorner: aCoord.m_Anchor = LB_CORNER; break;
877 case T_rbcorner: aCoord.m_Anchor = RB_CORNER; break;
878 case T_rtcorner: aCoord.m_Anchor = RT_CORNER; break;
879 default: Unexpected( CurText() ); break;
880 }
881 }
882}
883
884
886{
887 T token = NextTok();
888
889 if( token != T_NUMBER )
890 Expecting( T_NUMBER );
891
892 return atoi( CurText() );
893}
894
895
896int DRAWING_SHEET_PARSER::parseInt( int aMin, int aMax )
897{
898 int val = parseInt();
899
900 if( val < aMin )
901 val = aMin;
902 else if( val > aMax )
903 val = aMax;
904
905 return val;
906}
907
908
910{
911 T token = NextTok();
912
913 if( token != T_NUMBER )
914 Expecting( T_NUMBER );
915
916
917 return DSNLEXER::parseDouble();
918}
919
920
921// defaultDrawingSheet is the default drawing sheet using the S expr.
922extern const char defaultDrawingSheet[];
923
924
926{
927 SetPageLayout( defaultDrawingSheet, false, wxT( "default page" ) );
928}
929
930
932{
933 return wxString( defaultDrawingSheet );
934}
935
936
937// emptyDrawingSheet is a "empty" drawing sheet using the S expr.
938// there is a 0 length line to fool something somewhere.
939extern const char emptyDrawingSheet[];
940
941
943{
944 SetPageLayout( emptyDrawingSheet, false, wxT( "empty page" ) );
945}
946
947
949{
950 return wxString( emptyDrawingSheet );
951}
952
953
955{
956 static const wxString name( wxS( "empty.kicad_wks" ) );
957
958 return name;
959}
960
961
962bool DS_DATA_MODEL::LoadFromName( const wxString& aSheetName, const wxString& aBasePath, PROJECT* aProject,
963 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack, wxString* aMsg )
964{
965 if( aSheetName == EmptyLayoutName() )
966 {
968 return true;
969 }
970
971 FILENAME_RESOLVER resolver;
972 resolver.SetProject( aProject );
973 resolver.SetProgramBase( &Pgm() );
974
975 return LoadDrawingSheet( resolver.ResolvePath( aSheetName, aBasePath, std::move( aEmbeddedFilesStack ) ), aMsg );
976}
977
978
979void DS_DATA_MODEL::SetPageLayout( const char* aPageLayout, bool Append, const wxString& aSource )
980{
981 if( ! Append )
982 ClearList();
983
984 DRAWING_SHEET_PARSER parser( aPageLayout, wxT( "Sexpr_string" ) );
985
986 try
987 {
988 parser.Parse( this );
989 }
990 catch( ... )
991 {
992 // best efforts
993 }
994}
995
996
997bool DS_DATA_MODEL::LoadDrawingSheet( const wxString& aFullFileName, wxString* aMsg, bool aAppend )
998{
999 if( !aAppend )
1000 {
1001 if( aFullFileName.IsEmpty() )
1002 {
1004 return true; // we assume its fine / default init
1005 }
1006
1007 if( !wxFileExists( aFullFileName ) )
1008 {
1009 if( aMsg )
1010 *aMsg = _( "File not found." );
1011
1013 return false;
1014 }
1015 }
1016
1017 wxFFile wksFile( aFullFileName, wxS( "rb" ) );
1018
1019 if( ! wksFile.IsOpened() )
1020 {
1021 if( aMsg )
1022 *aMsg = _( "File could not be opened." );
1023
1024 if( !aAppend )
1026
1027 return false;
1028 }
1029
1030 size_t filelen = wksFile.Length();
1031 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(filelen+10);
1032
1033 if( wksFile.Read( buffer.get(), filelen ) != filelen )
1034 {
1035 if( aMsg )
1036 *aMsg = _( "Drawing sheet was not fully read." );
1037
1038 return false;
1039 }
1040 else
1041 {
1042 buffer[filelen]=0;
1043
1044 if( ! aAppend )
1045 ClearList();
1046
1047 DRAWING_SHEET_PARSER parser( buffer.get(), aFullFileName );
1048
1049 try
1050 {
1051 parser.Parse( this );
1052 }
1053 catch( const IO_ERROR& ioe )
1054 {
1055 if( aMsg )
1056 *aMsg = ioe.What();
1057
1058 return false;
1059 }
1060 catch( const std::bad_alloc& )
1061 {
1062 if( aMsg )
1063 *aMsg = _( "Ran out of memory." );
1064
1065 return false;
1066 }
1067 }
1068
1069 return true;
1070}
const char * name
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 SaveImageData.
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:400
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)
void SetGenerator(const wxString &aGenerator)
bool LoadFromName(const wxString &aSheetName, const wxString &aBasePath, PROJECT *aProject, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack, wxString *aMsg)
Populate the list from aSheetName, which is either EmptyLayoutName, an embedded file reference or a p...
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)
static const wxString & EmptyLayoutName()
Return the reserved drawing-sheet name that marks a design as deliberately having no sheet,...
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.
Provide an extensible class to resolve 3D model paths.
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Determine the full path of the given file name.
void SetProgramBase(PGM_BASE *aBase)
Set a pointer to the application's PGM_BASE instance used to extract the local env vars.
bool SetProject(const PROJECT *aProject, bool *flgChanged=nullptr)
Set the current KiCad project directory as the first entry in the model path list.
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:391
double g
Green component.
Definition color4d.h:392
double a
Alpha component.
Definition color4d.h:394
double b
Blue component.
Definition color4d.h:393
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
Container for project specific data.
Definition project.h:63
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition richio.h:225
const char emptyDrawingSheet[]
const char defaultDrawingSheet[]
wxString convertLegacyVariableRefs(const wxString &aTextbase)
@ FIRST_PAGE_ONLY
@ SUBSEQUENT_PAGES
@ RB_CORNER
@ RT_CORNER
@ LT_CORNER
@ LB_CORNER
constexpr int DS_MAX_REPEAT_COUNT
Upper bound on DS_DATA_ITEM::m_RepeatCount.
#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:30
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
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:707