/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include #include #include #include "sch_sexpr_plugin_common.h" #include using namespace TSCHEMATIC_T; static const char* emptyString = ""; void formatFill( OUTPUTFORMATTER* aFormatter, int aNestLevel, FILL_T aFillMode, const COLOR4D& aFillColor ) { const char* fillType; switch( aFillMode ) { default: case FILL_T::NO_FILL: fillType = "none"; break; case FILL_T::FILLED_SHAPE: fillType = "outline"; break; case FILL_T::FILLED_WITH_BG_BODYCOLOR: fillType = "background"; break; case FILL_T::FILLED_WITH_COLOR: fillType = "color"; break; } if( aFillMode == FILL_T::FILLED_WITH_COLOR ) { aFormatter->Print( aNestLevel, "(fill (type %s) (color %d %d %d %s))", fillType, KiROUND( aFillColor.r * 255.0 ), KiROUND( aFillColor.g * 255.0 ), KiROUND( aFillColor.b * 255.0 ), FormatDouble2Str( aFillColor.a ).c_str() ); } else { aFormatter->Print( aNestLevel, "(fill (type %s))", fillType ); } } const char* getPinElectricalTypeToken( ELECTRICAL_PINTYPE aType ) { switch( aType ) { case ELECTRICAL_PINTYPE::PT_INPUT: return SCHEMATIC_LEXER::TokenName( T_input ); case ELECTRICAL_PINTYPE::PT_OUTPUT: return SCHEMATIC_LEXER::TokenName( T_output ); case ELECTRICAL_PINTYPE::PT_BIDI: return SCHEMATIC_LEXER::TokenName( T_bidirectional ); case ELECTRICAL_PINTYPE::PT_TRISTATE: return SCHEMATIC_LEXER::TokenName( T_tri_state ); case ELECTRICAL_PINTYPE::PT_PASSIVE: return SCHEMATIC_LEXER::TokenName( T_passive ); case ELECTRICAL_PINTYPE::PT_NIC: return SCHEMATIC_LEXER::TokenName( T_free ); case ELECTRICAL_PINTYPE::PT_UNSPECIFIED: return SCHEMATIC_LEXER::TokenName( T_unspecified ); case ELECTRICAL_PINTYPE::PT_POWER_IN: return SCHEMATIC_LEXER::TokenName( T_power_in ); case ELECTRICAL_PINTYPE::PT_POWER_OUT: return SCHEMATIC_LEXER::TokenName( T_power_out ); case ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR: return SCHEMATIC_LEXER::TokenName( T_open_collector ); case ELECTRICAL_PINTYPE::PT_OPENEMITTER: return SCHEMATIC_LEXER::TokenName( T_open_emitter ); case ELECTRICAL_PINTYPE::PT_NC: return SCHEMATIC_LEXER::TokenName( T_no_connect ); default: wxFAIL_MSG( "Missing symbol library pin connection type" ); } return emptyString; } const char* getPinShapeToken( GRAPHIC_PINSHAPE aShape ) { switch( aShape ) { case GRAPHIC_PINSHAPE::LINE: return SCHEMATIC_LEXER::TokenName( T_line ); case GRAPHIC_PINSHAPE::INVERTED: return SCHEMATIC_LEXER::TokenName( T_inverted ); case GRAPHIC_PINSHAPE::CLOCK: return SCHEMATIC_LEXER::TokenName( T_clock ); case GRAPHIC_PINSHAPE::INVERTED_CLOCK: return SCHEMATIC_LEXER::TokenName( T_inverted_clock ); case GRAPHIC_PINSHAPE::INPUT_LOW: return SCHEMATIC_LEXER::TokenName( T_input_low ); case GRAPHIC_PINSHAPE::CLOCK_LOW: return SCHEMATIC_LEXER::TokenName( T_clock_low ); case GRAPHIC_PINSHAPE::OUTPUT_LOW: return SCHEMATIC_LEXER::TokenName( T_output_low ); case GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK: return SCHEMATIC_LEXER::TokenName( T_edge_clock_high ); case GRAPHIC_PINSHAPE::NONLOGIC: return SCHEMATIC_LEXER::TokenName( T_non_logic ); default: wxFAIL_MSG( "Missing symbol library pin shape type" ); } return emptyString; } EDA_ANGLE getPinAngle( int aOrientation ) { switch( aOrientation ) { case PIN_RIGHT: return ANGLE_0; case PIN_LEFT: return ANGLE_180; case PIN_UP: return ANGLE_90; case PIN_DOWN: return ANGLE_270; default: wxFAIL_MSG( "Missing symbol library pin orientation type" ); return ANGLE_0; } } const char* getSheetPinShapeToken( LABEL_FLAG_SHAPE aShape ) { switch( aShape ) { case LABEL_FLAG_SHAPE::L_INPUT: return SCHEMATIC_LEXER::TokenName( T_input ); case LABEL_FLAG_SHAPE::L_OUTPUT: return SCHEMATIC_LEXER::TokenName( T_output ); case LABEL_FLAG_SHAPE::L_BIDI: return SCHEMATIC_LEXER::TokenName( T_bidirectional ); case LABEL_FLAG_SHAPE::L_TRISTATE: return SCHEMATIC_LEXER::TokenName( T_tri_state ); case LABEL_FLAG_SHAPE::L_UNSPECIFIED: return SCHEMATIC_LEXER::TokenName( T_passive ); case LABEL_FLAG_SHAPE::F_DOT: return SCHEMATIC_LEXER::TokenName( T_dot ); case LABEL_FLAG_SHAPE::F_ROUND: return SCHEMATIC_LEXER::TokenName( T_round ); case LABEL_FLAG_SHAPE::F_DIAMOND: return SCHEMATIC_LEXER::TokenName( T_diamond ); case LABEL_FLAG_SHAPE::F_RECTANGLE: return SCHEMATIC_LEXER::TokenName( T_rectangle ); default: wxFAIL; return SCHEMATIC_LEXER::TokenName( T_passive ); } } EDA_ANGLE getSheetPinAngle( SHEET_SIDE aSide ) { switch( aSide ) { case SHEET_SIDE::UNDEFINED: case SHEET_SIDE::LEFT: return ANGLE_180; case SHEET_SIDE::RIGHT: return ANGLE_0; case SHEET_SIDE::TOP: return ANGLE_90; case SHEET_SIDE::BOTTOM: return ANGLE_270; default: wxFAIL; return ANGLE_0; } } const char* getTextTypeToken( KICAD_T aType ) { switch( aType ) { case SCH_TEXT_T: return SCHEMATIC_LEXER::TokenName( T_text ); case SCH_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_label ); case SCH_GLOBAL_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_global_label ); case SCH_HIER_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_hierarchical_label ); case SCH_DIRECTIVE_LABEL_T: return SCHEMATIC_LEXER::TokenName( T_netclass_flag ); default: wxFAIL; return SCHEMATIC_LEXER::TokenName( T_text ); } } void formatArc( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aArc, bool aIsPrivate, const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, const KIID& aUuid ) { aFormatter->Print( aNestLevel, "(arc%s (start %s) (mid %s) (end %s)\n", aIsPrivate ? " private" : "", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aArc->GetStart() ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aArc->GetArcMid() ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aArc->GetEnd() ).c_str() ); aStroke.Format( aFormatter, schIUScale, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); if( aUuid != niluuid ) aFormatter->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aUuid.AsString() ) ); aFormatter->Print( aNestLevel, ")\n" ); } void formatCircle( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aCircle, bool aIsPrivate, const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, const KIID& aUuid ) { aFormatter->Print( aNestLevel, "(circle%s (center %s %s) (radius %s)\n", aIsPrivate ? " private" : "", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aCircle->GetStart().x ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aCircle->GetStart().y ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aCircle->GetRadius() ).c_str() ); aStroke.Format( aFormatter, schIUScale, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); if( aUuid != niluuid ) aFormatter->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aUuid.AsString() ) ); aFormatter->Print( aNestLevel, ")\n" ); } void formatRect( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aRect, bool aIsPrivate, const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, const KIID& aUuid ) { aFormatter->Print( aNestLevel, "(rectangle%s (start %s %s) (end %s %s)\n", aIsPrivate ? " private" : "", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aRect->GetStart().x ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aRect->GetStart().y ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aRect->GetEnd().x ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, aRect->GetEnd().y ).c_str() ); aStroke.Format( aFormatter, schIUScale, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); if( aUuid != niluuid ) aFormatter->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aUuid.AsString() ) ); aFormatter->Print( aNestLevel, ")\n" ); } void formatBezier( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aBezier, bool aIsPrivate, const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, const KIID& aUuid ) { aFormatter->Print( aNestLevel, "(bezier%s (pts ", aIsPrivate ? " private" : "" ); for( const VECTOR2I& pt : { aBezier->GetStart(), aBezier->GetBezierC1(), aBezier->GetBezierC2(), aBezier->GetEnd() } ) { aFormatter->Print( 0, " (xy %s %s)", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pt.x ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pt.y ).c_str() ); } aFormatter->Print( 0, ")\n" ); // Closes pts token on same line. aStroke.Format( aFormatter, schIUScale, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); if( aUuid != niluuid ) aFormatter->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aUuid.AsString() ) ); aFormatter->Print( aNestLevel, ")\n" ); } void formatPoly( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aPolyLine, bool aIsPrivate, const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor, const KIID& aUuid ) { int newLine = 0; int lineCount = 1; aFormatter->Print( aNestLevel, "(polyline%s\n", aIsPrivate ? " private" : "" ); aFormatter->Print( aNestLevel + 1, "(pts" ); for( const VECTOR2I& pt : aPolyLine->GetPolyShape().Outline( 0 ).CPoints() ) { if( newLine == 4 || !ADVANCED_CFG::GetCfg().m_CompactSave ) { aFormatter->Print( 0, "\n" ); aFormatter->Print( aNestLevel + 2, "(xy %s %s)", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pt.x ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pt.y ).c_str() ); newLine = 0; lineCount += 1; } else { aFormatter->Print( 0, " (xy %s %s)", EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pt.x ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( schIUScale, pt.y ).c_str() ); } newLine += 1; } if( lineCount == 1 ) { aFormatter->Print( 0, ")\n" ); // Closes pts token on same line. } else { aFormatter->Print( 0, "\n" ); aFormatter->Print( aNestLevel + 1, ")\n" ); // Closes pts token with multiple lines. } aStroke.Format( aFormatter, schIUScale, aNestLevel + 1 ); aFormatter->Print( 0, "\n" ); formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor ); aFormatter->Print( 0, "\n" ); if( aUuid != niluuid ) aFormatter->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aUuid.AsString() ) ); aFormatter->Print( aNestLevel, ")\n" ); }