Commit a71857ba authored by Dick Hollenbeck's avatar Dick Hollenbeck Committed by Wayne Stambaugh

Commit Dick's Pcbnew s-expression file parser bug fixes.

* Apply Dick's patch along with a few minor changes to fix some clashes with
  changes in my branch.  Thanks Dick!
* Added missing DRAWSEGMENT line angle.
* Fix thru hole pad layer mask issue.
parent d3f95548
...@@ -70,11 +70,11 @@ else (KICAD_STABLE_VERSION ) ...@@ -70,11 +70,11 @@ else (KICAD_STABLE_VERSION )
endif(KICAD_STABLE_VERSION ) endif(KICAD_STABLE_VERSION )
# Nanometers must be enabled when USE_PCBNEW_SEXPR_FILE_FORMAT=ON. # Nanometers must be enabled when USE_PCBNEW_SEXPR_FILE_FORMAT=ON.
if( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES ) #if( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES )
set( TMP "The Pcbnew s-expression file format requires nano-meter internal units to be " ) # set( TMP "The Pcbnew s-expression file format requires nano-meter internal units to be " )
set( TMP "${TMP} enabled using -DUSE_PCBNEW_NANOMETRES=ON." ) # set( TMP "${TMP} enabled using -DUSE_PCBNEW_NANOMETRES=ON." )
message( FATAL_ERROR ${TMP} ) # message( FATAL_ERROR ${TMP} )
endif( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES ) #endif( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES )
#================================================ #================================================
# Set flags for GCC. # Set flags for GCC.
......
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here: * along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license, * or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc., * or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/** /**
* @file eda_text.cpp * @file eda_text.cpp
* @brief Implementation of base KiCad text object. * @brief Implementation of base KiCad text object.
*/ */
#include <eda_text.h> #include <eda_text.h>
#include <drawtxt.h> #include <drawtxt.h>
#include <macros.h> // MAX #include <macros.h> // MAX
#include <trigo.h> // RotatePoint #include <trigo.h> // RotatePoint
#include <class_drawpanel.h> // EDA_DRAW_PANEL #include <class_drawpanel.h> // EDA_DRAW_PANEL
// Conversion to application internal units defined at build time. // Conversion to application internal units defined at build time.
#if defined( PCBNEW ) #if defined( PCBNEW )
#include <class_board_item.h> #include <class_board_item.h>
#define MILS_TO_IU( x ) ( x * IU_PER_MILS ); #define MILS_TO_IU( x ) ( x * IU_PER_MILS );
#elif defined( EESCHEMA ) #elif defined( EESCHEMA )
#include <sch_item_struct.h> #include <sch_item_struct.h>
#define MILS_TO_IU( x ) ( x ) #define MILS_TO_IU( x ) ( x )
#else #else
#error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW." #error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW."
#endif #endif
EDA_TEXT::EDA_TEXT( const wxString& text ) EDA_TEXT::EDA_TEXT( const wxString& text )
{ {
m_Size.x = m_Size.y = MILS_TO_IU( DEFAULT_SIZE_TEXT ); // Width and height of font. m_Size.x = m_Size.y = MILS_TO_IU( DEFAULT_SIZE_TEXT ); // Width and height of font.
m_Orient = 0; // Rotation angle in 0.1 degrees. m_Orient = 0; // Rotation angle in 0.1 degrees.
m_Attributs = 0; m_Attributs = 0;
m_Mirror = false; // display mirror if true m_Mirror = false; // display mirror if true
m_HJustify = GR_TEXT_HJUSTIFY_CENTER; // Default horizontal justification is centered. m_HJustify = GR_TEXT_HJUSTIFY_CENTER; // Default horizontal justification is centered.
m_VJustify = GR_TEXT_VJUSTIFY_CENTER; // Default vertical justification is centered. m_VJustify = GR_TEXT_VJUSTIFY_CENTER; // Default vertical justification is centered.
m_Thickness = 0; // thickness m_Thickness = 0; // thickness
m_Italic = false; // true = italic shape. m_Italic = false; // true = italic shape.
m_Bold = false; m_Bold = false;
m_MultilineAllowed = false; // Set to true for multiline text. m_MultilineAllowed = false; // Set to true for multiline text.
m_Text = text; m_Text = text;
} }
EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText ) EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText )
{ {
m_Pos = aText.m_Pos; m_Pos = aText.m_Pos;
m_Size = aText.m_Size; m_Size = aText.m_Size;
m_Orient = aText.m_Orient; m_Orient = aText.m_Orient;
m_Attributs = aText.m_Attributs; m_Attributs = aText.m_Attributs;
m_Mirror = aText.m_Mirror; m_Mirror = aText.m_Mirror;
m_HJustify = aText.m_HJustify; m_HJustify = aText.m_HJustify;
m_VJustify = aText.m_VJustify; m_VJustify = aText.m_VJustify;
m_Thickness = aText.m_Thickness; m_Thickness = aText.m_Thickness;
m_Italic = aText.m_Italic; m_Italic = aText.m_Italic;
m_Bold = aText.m_Bold; m_Bold = aText.m_Bold;
m_MultilineAllowed = aText.m_MultilineAllowed; m_MultilineAllowed = aText.m_MultilineAllowed;
m_Text = aText.m_Text; m_Text = aText.m_Text;
} }
EDA_TEXT::~EDA_TEXT() EDA_TEXT::~EDA_TEXT()
{ {
} }
int EDA_TEXT::LenSize( const wxString& aLine ) const int EDA_TEXT::LenSize( const wxString& aLine ) const
{ {
return ReturnGraphicTextWidth( aLine, m_Size.x, m_Italic, m_Bold ); return ReturnGraphicTextWidth( aLine, m_Size.x, m_Italic, m_Bold );
} }
EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
{ {
EDA_RECT rect; EDA_RECT rect;
wxPoint pos; wxPoint pos;
wxArrayString* list = NULL; wxArrayString* list = NULL;
wxString text = m_Text; wxString text = m_Text;
int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness; int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness;
if( m_MultilineAllowed ) if( m_MultilineAllowed )
{ {
list = wxStringSplit( m_Text, '\n' ); list = wxStringSplit( m_Text, '\n' );
if ( list->GetCount() ) // GetCount() == 0 for void strings if ( list->GetCount() ) // GetCount() == 0 for void strings
{ {
if( aLine >= 0 && (aLine < (int)list->GetCount()) ) if( aLine >= 0 && (aLine < (int)list->GetCount()) )
text = list->Item( aLine ); text = list->Item( aLine );
else else
text = list->Item( 0 ); text = list->Item( 0 );
} }
} }
// calculate the H and V size // calculate the H and V size
int dx = LenSize( text ); int dx = LenSize( text );
int dy = GetInterline(); int dy = GetInterline();
/* Creates bounding box (rectangle) for an horizontal text */ /* Creates bounding box (rectangle) for an horizontal text */
wxSize textsize = wxSize( dx, dy ); wxSize textsize = wxSize( dx, dy );
if( aInvertY ) if( aInvertY )
rect.SetOrigin( m_Pos.x, -m_Pos.y ); rect.SetOrigin( m_Pos.x, -m_Pos.y );
else else
rect.SetOrigin( m_Pos ); rect.SetOrigin( m_Pos );
// extra dy interval for letters like j and y and ] // extra dy interval for letters like j and y and ]
int extra_dy = dy - m_Size.y; int extra_dy = dy - m_Size.y;
rect.Move( wxPoint( 0, -extra_dy / 2 ) ); // move origin by the half extra interval rect.Move( wxPoint( 0, -extra_dy / 2 ) ); // move origin by the half extra interval
// for multiline texts and aLine < 0, merge all rectangles // for multiline texts and aLine < 0, merge all rectangles
if( m_MultilineAllowed && list && aLine < 0 ) if( m_MultilineAllowed && list && aLine < 0 )
{ {
for( unsigned ii = 1; ii < list->GetCount(); ii++ ) for( unsigned ii = 1; ii < list->GetCount(); ii++ )
{ {
text = list->Item( ii ); text = list->Item( ii );
dx = LenSize( text ); dx = LenSize( text );
textsize.x = MAX( textsize.x, dx ); textsize.x = MAX( textsize.x, dx );
textsize.y += dy; textsize.y += dy;
} }
} }
delete list; delete list;
rect.SetSize( textsize ); rect.SetSize( textsize );
/* Now, calculate the rect origin, according to text justification /* Now, calculate the rect origin, according to text justification
* At this point the rectangle origin is the text origin (m_Pos). * At this point the rectangle origin is the text origin (m_Pos).
* This is true only for left and top text justified texts (using top to bottom Y axis * This is true only for left and top text justified texts (using top to bottom Y axis
* orientation). and must be recalculated for others justifications * orientation). and must be recalculated for others justifications
* also, note the V justification is relative to the first line * also, note the V justification is relative to the first line
*/ */
switch( m_HJustify ) switch( m_HJustify )
{ {
case GR_TEXT_HJUSTIFY_LEFT: case GR_TEXT_HJUSTIFY_LEFT:
if( m_Mirror ) if( m_Mirror )
rect.SetX( rect.GetX() - rect.GetWidth() ); rect.SetX( rect.GetX() - rect.GetWidth() );
break; break;
case GR_TEXT_HJUSTIFY_CENTER: case GR_TEXT_HJUSTIFY_CENTER:
rect.SetX( rect.GetX() - (rect.GetWidth() / 2) ); rect.SetX( rect.GetX() - (rect.GetWidth() / 2) );
break; break;
case GR_TEXT_HJUSTIFY_RIGHT: case GR_TEXT_HJUSTIFY_RIGHT:
if( !m_Mirror ) if( !m_Mirror )
rect.SetX( rect.GetX() - rect.GetWidth() ); rect.SetX( rect.GetX() - rect.GetWidth() );
break; break;
} }
dy = m_Size.y + thickness; dy = m_Size.y + thickness;
switch( m_VJustify ) switch( m_VJustify )
{ {
case GR_TEXT_VJUSTIFY_TOP: case GR_TEXT_VJUSTIFY_TOP:
break; break;
case GR_TEXT_VJUSTIFY_CENTER: case GR_TEXT_VJUSTIFY_CENTER:
rect.SetY( rect.GetY() - (dy / 2) ); rect.SetY( rect.GetY() - (dy / 2) );
break; break;
case GR_TEXT_VJUSTIFY_BOTTOM: case GR_TEXT_VJUSTIFY_BOTTOM:
rect.SetY( rect.GetY() - dy ); rect.SetY( rect.GetY() - dy );
break; break;
} }
rect.Inflate( thickness / 2 ); rect.Inflate( thickness / 2 );
rect.Normalize(); // Make h and v sizes always >= 0 rect.Normalize(); // Make h and v sizes always >= 0
return rect; return rect;
} }
bool EDA_TEXT::TextHitTest( const wxPoint& aPoint, int aAccuracy ) const bool EDA_TEXT::TextHitTest( const wxPoint& aPoint, int aAccuracy ) const
{ {
EDA_RECT rect = GetTextBox( -1 ); // Get the full text area. EDA_RECT rect = GetTextBox( -1 ); // Get the full text area.
wxPoint location = aPoint; wxPoint location = aPoint;
rect.Inflate( aAccuracy ); rect.Inflate( aAccuracy );
RotatePoint( &location, m_Pos, -m_Orient ); RotatePoint( &location, m_Pos, -m_Orient );
return rect.Contains( location ); return rect.Contains( location );
} }
bool EDA_TEXT::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy ) const bool EDA_TEXT::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy ) const
{ {
EDA_RECT rect = aRect; EDA_RECT rect = aRect;
rect.Inflate( aAccuracy ); rect.Inflate( aAccuracy );
if( aContains ) if( aContains )
return rect.Contains( GetTextBox( -1 ) ); return rect.Contains( GetTextBox( -1 ) );
return rect.Intersects( GetTextBox( -1 ) ); return rect.Intersects( GetTextBox( -1 ) );
} }
void EDA_TEXT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, void EDA_TEXT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset,
EDA_COLOR_T aColor, int aDrawMode, EDA_COLOR_T aColor, int aDrawMode,
EDA_DRAW_MODE_T aFillMode, EDA_COLOR_T aAnchor_color ) EDA_DRAW_MODE_T aFillMode, EDA_COLOR_T aAnchor_color )
{ {
if( m_MultilineAllowed ) if( m_MultilineAllowed )
{ {
wxPoint pos = m_Pos; wxPoint pos = m_Pos;
wxArrayString* list = wxStringSplit( m_Text, '\n' ); wxArrayString* list = wxStringSplit( m_Text, '\n' );
wxPoint offset; wxPoint offset;
offset.y = GetInterline(); offset.y = GetInterline();
RotatePoint( &offset, m_Orient ); RotatePoint( &offset, m_Orient );
for( unsigned i = 0; i<list->Count(); i++ ) for( unsigned i = 0; i<list->Count(); i++ )
{ {
wxString txt = list->Item( i ); wxString txt = list->Item( i );
DrawOneLineOfText( aPanel, DrawOneLineOfText( aPanel,
aDC, aDC,
aOffset, aOffset,
aColor, aColor,
aDrawMode, aDrawMode,
aFillMode, aFillMode,
i ? UNSPECIFIED : aAnchor_color, i ? UNSPECIFIED : aAnchor_color,
txt, txt,
pos ); pos );
pos += offset; pos += offset;
} }
delete (list); delete (list);
} }
else else
DrawOneLineOfText( aPanel, DrawOneLineOfText( aPanel,
aDC, aDC,
aOffset, aOffset,
aColor, aColor,
aDrawMode, aDrawMode,
aFillMode, aFillMode,
aAnchor_color, aAnchor_color,
m_Text, m_Text,
m_Pos ); m_Pos );
} }
void EDA_TEXT::DrawOneLineOfText( EDA_DRAW_PANEL* aPanel, wxDC* aDC, void EDA_TEXT::DrawOneLineOfText( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
const wxPoint& aOffset, EDA_COLOR_T aColor, const wxPoint& aOffset, EDA_COLOR_T aColor,
int aDrawMode, EDA_DRAW_MODE_T aFillMode, int aDrawMode, EDA_DRAW_MODE_T aFillMode,
EDA_COLOR_T aAnchor_color, EDA_COLOR_T aAnchor_color,
wxString& aText, wxPoint aPos ) wxString& aText, wxPoint aPos )
{ {
int width = m_Thickness; int width = m_Thickness;
if( aFillMode == LINE ) if( aFillMode == LINE )
width = 0; width = 0;
if( aDrawMode != -1 ) if( aDrawMode != -1 )
GRSetDrawMode( aDC, aDrawMode ); GRSetDrawMode( aDC, aDrawMode );
/* Draw text anchor, if allowed */ /* Draw text anchor, if allowed */
if( aAnchor_color != UNSPECIFIED ) if( aAnchor_color != UNSPECIFIED )
{ {
int anchor_size = aDC->DeviceToLogicalXRel( 2 ); int anchor_size = aDC->DeviceToLogicalXRel( 2 );
aAnchor_color = (EDA_COLOR_T) ( aAnchor_color & MASKCOLOR ); aAnchor_color = (EDA_COLOR_T) ( aAnchor_color & MASKCOLOR );
int cX = aPos.x + aOffset.x; int cX = aPos.x + aOffset.x;
int cY = aPos.y + aOffset.y; int cY = aPos.y + aOffset.y;
GRLine( aPanel->GetClipBox(), aDC, cX - anchor_size, cY, GRLine( aPanel->GetClipBox(), aDC, cX - anchor_size, cY,
cX + anchor_size, cY, 0, aAnchor_color ); cX + anchor_size, cY, 0, aAnchor_color );
GRLine( aPanel->GetClipBox(), aDC, cX, cY - anchor_size, GRLine( aPanel->GetClipBox(), aDC, cX, cY - anchor_size,
cX, cY + anchor_size, 0, aAnchor_color ); cX, cY + anchor_size, 0, aAnchor_color );
} }
if( aFillMode == SKETCH ) if( aFillMode == SKETCH )
width = -width; width = -width;
wxSize size = m_Size; wxSize size = m_Size;
if( m_Mirror ) if( m_Mirror )
size.x = -size.x; size.x = -size.x;
DrawGraphicText( aPanel, aDC, aOffset + aPos, aColor, aText, m_Orient, size, DrawGraphicText( aPanel, aDC, aOffset + aPos, aColor, aText, m_Orient, size,
m_HJustify, m_VJustify, width, m_Italic, m_Bold ); m_HJustify, m_VJustify, width, m_Italic, m_Bold );
} }
wxString EDA_TEXT::GetTextStyleName() wxString EDA_TEXT::GetTextStyleName()
{ {
int style = 0; int style = 0;
if( m_Italic ) if( m_Italic )
style = 1; style = 1;
if( m_Bold ) if( m_Bold )
style += 2; style += 2;
wxString stylemsg[4] = { wxString stylemsg[4] = {
_("Normal"), _("Normal"),
_("Italic"), _("Italic"),
_("Bold"), _("Bold"),
_("Bold+Italic") _("Bold+Italic")
}; };
return stylemsg[style]; return stylemsg[style];
} }
bool EDA_TEXT::IsDefaultFormatting() const bool EDA_TEXT::IsDefaultFormatting() const
{ {
return ( ( m_Size.x == DEFAULT_SIZE_TEXT ) return ( ( m_Size.x == DEFAULT_SIZE_TEXT )
&& ( m_Size.y == DEFAULT_SIZE_TEXT ) && ( m_Size.y == DEFAULT_SIZE_TEXT )
&& ( m_Attributs == 0 ) && ( m_Attributs == 0 )
&& ( m_Mirror == false ) && ( m_Mirror == false )
&& ( m_HJustify == GR_TEXT_HJUSTIFY_CENTER ) && ( m_HJustify == GR_TEXT_HJUSTIFY_CENTER )
&& ( m_VJustify == GR_TEXT_VJUSTIFY_CENTER ) && ( m_VJustify == GR_TEXT_VJUSTIFY_CENTER )
&& ( m_Thickness == 0 ) && ( m_Thickness == 0 )
&& ( m_Italic == false ) && ( m_Italic == false )
&& ( m_Bold == false ) && ( m_Bold == false )
&& ( m_MultilineAllowed == false ) ); && ( m_MultilineAllowed == false ) );
} }
void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR ) throw( IO_ERROR )
{ {
if( !IsDefaultFormatting() ) if( !IsDefaultFormatting() )
{ {
aFormatter->Print( aNestLevel+1, "(effects\n" ); aFormatter->Print( aNestLevel+1, "(effects\n" );
if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) || m_Bold if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) || m_Bold
|| m_Italic ) || m_Italic )
{ {
aFormatter->Print( aNestLevel+2, "(font" ); aFormatter->Print( aNestLevel+2, "(font" );
// Add font support here at some point in the future. // Add font support here at some point in the future.
if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) ) if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) )
aFormatter->Print( 0, " (size %s %s)", FMT_IU( m_Size.GetHeight() ).c_str(), aFormatter->Print( 0, " (size %s %s)", FMT_IU( m_Size.GetHeight() ).c_str(),
FMT_IU( m_Size.GetWidth() ).c_str() ); FMT_IU( m_Size.GetWidth() ).c_str() );
if( m_Thickness != 0 ) if( m_Thickness != 0 )
aFormatter->Print( 0, " (thickness %s)", FMT_IU( m_Thickness ).c_str() ); aFormatter->Print( 0, " (thickness %s)", FMT_IU( GetThickness() ).c_str() );
if( m_Bold ) if( m_Bold )
aFormatter->Print( 0, " bold" ); aFormatter->Print( 0, " bold" );
if( m_Bold ) if( m_Bold )
aFormatter->Print( 0, " italic" ); aFormatter->Print( 0, " italic" );
aFormatter->Print( 0, ")\n"); aFormatter->Print( 0, ")\n");
} }
if( m_Mirror || ( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) if( m_Mirror || ( m_HJustify != GR_TEXT_HJUSTIFY_CENTER )
|| ( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) ) || ( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) )
{ {
aFormatter->Print( aNestLevel+2, "(justify"); aFormatter->Print( aNestLevel+2, "(justify");
if( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) if( m_HJustify != GR_TEXT_HJUSTIFY_CENTER )
aFormatter->Print( 0, (m_HJustify == GR_TEXT_HJUSTIFY_LEFT) ? " left" : " right" ); aFormatter->Print( 0, (m_HJustify == GR_TEXT_HJUSTIFY_LEFT) ? " left" : " right" );
if( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) if( m_VJustify != GR_TEXT_VJUSTIFY_CENTER )
aFormatter->Print( 0, (m_VJustify == GR_TEXT_VJUSTIFY_TOP) ? " top" : " bottom" ); aFormatter->Print( 0, (m_VJustify == GR_TEXT_VJUSTIFY_TOP) ? " top" : " bottom" );
if( m_Mirror ) if( m_Mirror )
aFormatter->Print( 0, " mirror" ); aFormatter->Print( 0, " mirror" );
aFormatter->Print( 0, ")\n" ); aFormatter->Print( 0, ")\n" );
} }
// As of now the only place this is used is in Eeschema to hide or show the text. // As of now the only place this is used is in Eeschema to hide or show the text.
if( m_Attributs ) if( m_Attributs )
aFormatter->Print( aNestLevel+2, "hide\n" ); aFormatter->Print( aNestLevel+2, "hide\n" );
aFormatter->Print( aNestLevel+1, ")\n" ); aFormatter->Print( aNestLevel+1, ")\n" );
} }
} }
...@@ -120,6 +120,7 @@ page ...@@ -120,6 +120,7 @@ page
path path
pcb_text_size pcb_text_size
pcb_text_width pcb_text_width
pcbplotparams
placed placed
plus plus
polygon polygon
......
...@@ -93,13 +93,23 @@ std::string BOARD_ITEM::FormatInternalUnits( int aValue ) ...@@ -93,13 +93,23 @@ std::string BOARD_ITEM::FormatInternalUnits( int aValue )
{ {
char buf[50]; char buf[50];
#if defined( USE_PCBNEW_NANOMETRES ) double mm = aValue / IU_PER_MM;
int nm = aValue;
#else int len;
int nm = KIROUND( ( aValue / 10000.0 ) * 25.4 * 1e6 );
#endif if( mm != 0.0 && fabs( mm ) <= 0.0001 )
{
len = sprintf( buf, "%.10f", mm );
int len = snprintf( buf, 49, "%g", nm / 1e6 ); while( --len > 0 && buf[len] == '0' )
buf[len] = '\0';
++len;
}
else
{
len = sprintf( buf, "%.10g", mm );
}
return std::string( buf, len ); return std::string( buf, len );
} }
......
...@@ -209,6 +209,7 @@ public: ...@@ -209,6 +209,7 @@ public:
const wxString& GetNetName() const { return m_Netname; }; const wxString& GetNetName() const { return m_Netname; };
void SetNetName( const wxString& aName ) { m_Netname = aName; } void SetNetName( const wxString& aName ) { m_Netname = aName; }
/// How to fill areas: 0 = use filled polygons, 1 => fill with segments.
void SetFillMode( int aFillMode ) { m_FillMode = aFillMode; } void SetFillMode( int aFillMode ) { m_FillMode = aFillMode; }
int GetFillMode() const { return m_FillMode; } int GetFillMode() const { return m_FillMode; }
...@@ -550,7 +551,7 @@ public: ...@@ -550,7 +551,7 @@ public:
int m_ZoneClearance; // clearance value int m_ZoneClearance; // clearance value
int m_ZoneMinThickness; // Min thickness value in filled areas int m_ZoneMinThickness; // Min thickness value in filled areas
// How to fill areas: 0 = use filled polygons, != 0 fill with segments. /// How to fill areas: 0 => use filled polygons, 1 => fill with segments.
int m_FillMode; int m_FillMode;
// number of segments to convert a circle to a polygon (uses // number of segments to convert a circle to a polygon (uses
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <class_drawsegment.h> #include <class_drawsegment.h>
#include <class_mire.h> #include <class_mire.h>
#include <class_edge_mod.h> #include <class_edge_mod.h>
#include <pcb_plot_params.h>
#include <zones.h> #include <zones.h>
#include <kicad_plugin.h> #include <kicad_plugin.h>
#include <pcb_parser.h> #include <pcb_parser.h>
...@@ -324,6 +325,8 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const ...@@ -324,6 +325,8 @@ void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
m_out->Print( aNestLevel+1, "(visible_elements %X)\n", m_out->Print( aNestLevel+1, "(visible_elements %X)\n",
aBoard->GetDesignSettings().GetVisibleElements() ); aBoard->GetDesignSettings().GetVisibleElements() );
// aBoard->GetPlotOptions().Format( m_out, aNestLevel+1 );
m_out->Print( aNestLevel, ")\n\n" ); m_out->Print( aNestLevel, ")\n\n" );
...@@ -448,9 +451,10 @@ void PCB_IO::format( DRAWSEGMENT* aSegment, int aNestLevel ) const ...@@ -448,9 +451,10 @@ void PCB_IO::format( DRAWSEGMENT* aSegment, int aNestLevel ) const
switch( aSegment->GetShape() ) switch( aSegment->GetShape() )
{ {
case S_SEGMENT: // Line case S_SEGMENT: // Line
m_out->Print( aNestLevel, "(gr_line (pts (xy %s) (xy %s))", m_out->Print( aNestLevel, "(gr_line (pts (xy %s) (xy %s)) (angle %s)",
FMT_IU( aSegment->GetStart() ).c_str(), FMT_IU( aSegment->GetStart() ).c_str(),
FMT_IU( aSegment->GetEnd() ).c_str() ); FMT_IU( aSegment->GetEnd() ).c_str(),
FMT_ANGLE( aSegment->GetAngle() ).c_str() );
break; break;
case S_CIRCLE: // Circle case S_CIRCLE: // Circle
...@@ -863,11 +867,17 @@ void PCB_IO::format( TEXTE_MODULE* aText, int aNestLevel ) const ...@@ -863,11 +867,17 @@ void PCB_IO::format( TEXTE_MODULE* aText, int aNestLevel ) const
if( parent ) if( parent )
orient += parent->GetOrientation(); orient += parent->GetOrientation();
m_out->Print( aNestLevel, "(fp_text %s %s (at %s %s)%s\n", m_out->Print( aNestLevel, "(fp_text %s %s (at %s %s)",
m_out->Quotew( type ).c_str(), m_out->Quotew( type ).c_str(),
m_out->Quotew( aText->GetText() ).c_str(), m_out->Quotew( aText->GetText() ).c_str(),
FMT_IU( aText->GetPos0() ).c_str(), FMT_ANGLE( orient ).c_str(), FMT_IU( aText->GetPos0() ).c_str(), FMT_ANGLE( orient ).c_str() );
(!aText->IsVisible()) ? " hide" : "" );
formatLayer( aText );
if( !aText->IsVisible() )
m_out->Print( 0, " hide" );
m_out->Print( 0, "\n" );
aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl ); aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl );
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2012 CERN * Copyright (C) 2012 CERN
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here: * along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license, * or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc., * or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/** /**
* @file pcb_parser.h * @file pcb_parser.h
* @brief Pcbnew s-expression file format parser definition. * @brief Pcbnew s-expression file format parser definition.
*/ */
#ifndef _PCBNEW_PARSER_H_ #ifndef _PCBNEW_PARSER_H_
#define _PCBNEW_PARSER_H_ #define _PCBNEW_PARSER_H_
#include <pcb_lexer.h> #include <pcb_lexer.h>
#include <wx/hashmap.h> #include <wx/hashmap.h>
using namespace PCB; using namespace PCB;
class BOARD; class BOARD;
class BOARD_ITEM; class BOARD_ITEM;
class D_PAD; class D_PAD;
class EDGE_MODULE; class DIMENSION;
class TEXTE_MODULE; class DRAWSEGMENT;
class TEXTE_PCB; class EDGE_MODULE;
class MODULE; class TEXTE_MODULE;
class PCB_TARGET; class TEXTE_PCB;
class S3D_MASTER; class MODULE;
class ZONE_CONTAINER; class PCB_TARGET;
class S3D_MASTER;
class ZONE_CONTAINER;
WX_DECLARE_STRING_HASH_MAP( int, LAYER_HASH_MAP );
WX_DECLARE_STRING_HASH_MAP( int, LAYER_HASH_MAP );
#define USE_LAYER_NAMES 1 // Set to 0 to format and parse layers by index number.
#define USE_LAYER_NAMES 1 // Set to 0 to format and parse layers by index number.
/**
* Class PCB_PARSER
* reads a Pcbnew s-expression fromatted #LINE_READER object and returns the appropriate /**
* #BOARD_ITEM object. * Class PCB_PARSER
*/ * reads a Pcbnew s-expression fromatted #LINE_READER object and returns the appropriate
class PCB_PARSER : public PCB_LEXER * #BOARD_ITEM object.
{ */
BOARD* m_board; class PCB_PARSER : public PCB_LEXER
LAYER_HASH_MAP m_layerMap; //< Map layer name to it's index saved in BOARD::m_Layer. {
BOARD* m_board;
void parseHeader() throw( IO_ERROR, PARSE_ERROR ); LAYER_HASH_MAP m_layerMap; //< Map layer name to it's index saved in BOARD::m_Layer.
void parseGeneralSection() throw( IO_ERROR, PARSE_ERROR );
void parsePAGE_INFO() throw( IO_ERROR, PARSE_ERROR ); void parseHeader() throw( IO_ERROR, PARSE_ERROR );
void parseTITLE_BLOCK() throw( IO_ERROR, PARSE_ERROR ); void parseGeneralSection() throw( IO_ERROR, PARSE_ERROR );
void parseLayers() throw( IO_ERROR, PARSE_ERROR ); void parsePAGE_INFO() throw( IO_ERROR, PARSE_ERROR );
void parseSetup() throw( IO_ERROR, PARSE_ERROR ); void parseTITLE_BLOCK() throw( IO_ERROR, PARSE_ERROR );
void parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR ); void parseLayers() throw( IO_ERROR, PARSE_ERROR );
void parseNETCLASS() throw( IO_ERROR, PARSE_ERROR ); void parseSetup() throw( IO_ERROR, PARSE_ERROR );
void parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR ); void parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR );
void parseTEXTE_PCB( TEXTE_PCB* aText = NULL ) throw( IO_ERROR, PARSE_ERROR ); void parseNETCLASS() throw( IO_ERROR, PARSE_ERROR );
void parseDIMENSION() throw( IO_ERROR, PARSE_ERROR ); DRAWSEGMENT* parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR );
void parseMODULE() throw( IO_ERROR, PARSE_ERROR ); TEXTE_PCB* parseTEXTE_PCB() throw( IO_ERROR, PARSE_ERROR );
TEXTE_MODULE* parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR ); DIMENSION* parseDIMENSION() throw( IO_ERROR, PARSE_ERROR );
EDGE_MODULE* parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR ); MODULE* parseMODULE() throw( IO_ERROR, PARSE_ERROR );
D_PAD* parseD_PAD() throw( IO_ERROR, PARSE_ERROR ); TEXTE_MODULE* parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR );
TRACK* parseTRACK() throw( IO_ERROR, PARSE_ERROR ); EDGE_MODULE* parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR );
SEGVIA* parseSEGVIA() throw( IO_ERROR, PARSE_ERROR ); D_PAD* parseD_PAD() throw( IO_ERROR, PARSE_ERROR );
ZONE_CONTAINER* parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ); TRACK* parseTRACK() throw( IO_ERROR, PARSE_ERROR );
PCB_TARGET* parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR ); SEGVIA* parseSEGVIA() throw( IO_ERROR, PARSE_ERROR );
BOARD* parseBOARD() throw( IO_ERROR, PARSE_ERROR ); ZONE_CONTAINER* parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR );
PCB_TARGET* parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR );
BOARD* parseBOARD() throw( IO_ERROR, PARSE_ERROR );
/**
* Function lookUpLayer
* parses the current token for the layer definition of a #BOARD_ITEM object. /**
* * Function lookUpLayer
* @throw IO_ERROR if the layer is not valid. * parses the current token for the layer definition of a #BOARD_ITEM object.
* @throw PARSE_ERROR if the layer syntax is incorrect. *
* @return The index the parsed #BOARD_ITEM layer. * @throw IO_ERROR if the layer is not valid.
*/ * @throw PARSE_ERROR if the layer syntax is incorrect.
int lookUpLayer() throw( PARSE_ERROR, IO_ERROR ); * @return The index the parsed #BOARD_ITEM layer.
*/
/** int lookUpLayer() throw( PARSE_ERROR, IO_ERROR );
* Function parseBoardItemLayer
* parses the layer definition of a #BOARD_ITEM object. /**
* * Function parseBoardItemLayer
* @throw IO_ERROR if the layer is not valid. * parses the layer definition of a #BOARD_ITEM object.
* @throw PARSE_ERROR if the layer syntax is incorrect. *
* @return The index the parsed #BOARD_ITEM layer. * @throw IO_ERROR if the layer is not valid.
*/ * @throw PARSE_ERROR if the layer syntax is incorrect.
int parseBoardItemLayer() throw( IO_ERROR, PARSE_ERROR ); * @return The index the parsed #BOARD_ITEM layer.
*/
/** int parseBoardItemLayer() throw( IO_ERROR, PARSE_ERROR );
* Function parseBoardItemLayersAsMask
* parses the layers definition of a #BOARD_ITEM object. /**
* * Function parseBoardItemLayersAsMask
* @throw IO_ERROR if any of the layers is not valid. * parses the layers definition of a #BOARD_ITEM object.
* @throw PARSE_ERROR if the layers syntax is incorrect. *
* @return The mask of layers the parsed #BOARD_ITEM is on. * @throw IO_ERROR if any of the layers is not valid.
*/ * @throw PARSE_ERROR if the layers syntax is incorrect.
int parseBoardItemLayersAsMask() throw( PARSE_ERROR, IO_ERROR ); * @return The mask of layers the parsed #BOARD_ITEM is on.
*/
/** int parseBoardItemLayersAsMask() throw( PARSE_ERROR, IO_ERROR );
* Function parseXY
* parses a coordinate pair (xy X Y) in board units (mm). /**
* * Function parseXY
* The parser checks if the previous token was T_LEFT and parses the remainder of * parses a coordinate pair (xy X Y) in board units (mm).
* the token syntax. This is used when parsing a list of coorinate points. This *
* way the parser can be used in either case. * The parser checks if the previous token was T_LEFT and parses the remainder of
* * the token syntax. This is used when parsing a list of coorinate points. This
* @throw PARSE_ERROR if the coordinate pair syntax is incorrect. * way the parser can be used in either case.
* @return A wxPoint object containing the coordinate pair. *
*/ * @throw PARSE_ERROR if the coordinate pair syntax is incorrect.
wxPoint parseXY() throw( PARSE_ERROR ); * @return A wxPoint object containing the coordinate pair.
*/
void parseXY( int* aX, int* aY ) throw( PARSE_ERROR ); wxPoint parseXY() throw( PARSE_ERROR );
/** void parseXY( int* aX, int* aY ) throw( PARSE_ERROR );
* Function parseEDA_TEXT
* parses the common settings for any object derived from #EDA_TEXT. /**
* * Function parseEDA_TEXT
* @throw PARSE_ERROR if the text syntax is not valid. * parses the common settings for any object derived from #EDA_TEXT.
* @param aText A point to the #EDA_TEXT object to save the parsed settings into. *
*/ * @throw PARSE_ERROR if the text syntax is not valid.
void parseEDA_TEXT( EDA_TEXT* aText ) throw( PARSE_ERROR ); * @param aText A point to the #EDA_TEXT object to save the parsed settings into.
*/
S3D_MASTER* parse3DModel() throw( PARSE_ERROR ); void parseEDA_TEXT( EDA_TEXT* aText ) throw( PARSE_ERROR );
/** S3D_MASTER* parse3DModel() throw( PARSE_ERROR );
* Function parseDouble
* parses the current token as an ASCII numeric string with possible leading whitespace into /**
* a double precision floating point number. * Function parseDouble
* * parses the current token as an ASCII numeric string with possible leading whitespace into
* @throw IO_ERROR if an error occurs attempting to convert the current token. * a double precision floating point number.
* @return The result of the parsed token. *
*/ * @throw IO_ERROR if an error occurs attempting to convert the current token.
double parseDouble() throw( IO_ERROR ); * @return The result of the parsed token.
*/
inline double parseDouble( const char* aExpected ) throw( IO_ERROR ) double parseDouble() throw( IO_ERROR );
{
NeedNUMBER( aExpected ); inline double parseDouble( const char* aExpected ) throw( IO_ERROR )
return parseDouble(); {
} NeedNUMBER( aExpected );
return parseDouble();
inline double parseDouble( T aToken ) throw( IO_ERROR ) }
{
return parseDouble( GetTokenText( aToken ) ); inline double parseDouble( T aToken ) throw( IO_ERROR )
} {
return parseDouble( GetTokenText( aToken ) );
inline int parseBoardUnits() throw( IO_ERROR ) }
{
// There should be no rounding issues here, since the values in the file are in mm inline int parseBoardUnits() throw( IO_ERROR )
// and get converted to nano-meters. This product should be an integer, exactly. {
return int( parseDouble() * 1e6 ); // There should be no rounding issues here, since the values in the file are in mm
} // and get converted to nano-meters. This product should be an integer, exactly.
return int( parseDouble() * IU_PER_MM );
inline int parseBoardUnits( const char* aExpected ) throw( PARSE_ERROR ) }
{
return KIROUND( parseDouble( aExpected ) * 1e6 ); inline int parseBoardUnits( const char* aExpected ) throw( PARSE_ERROR )
} {
return KIROUND( parseDouble( aExpected ) * IU_PER_MM );
inline int parseBoardUnits( T aToken ) throw( PARSE_ERROR ) }
{
return parseBoardUnits( GetTokenText( aToken ) ); inline int parseBoardUnits( T aToken ) throw( PARSE_ERROR )
} {
return parseBoardUnits( GetTokenText( aToken ) );
inline int parseInt() throw( PARSE_ERROR ) }
{
return (int)strtol( CurText(), NULL, 10 ); inline int parseInt() throw( PARSE_ERROR )
} {
return (int)strtol( CurText(), NULL, 10 );
inline int parseInt( const char* aExpected ) throw( PARSE_ERROR ) }
{
NeedNUMBER( aExpected ); inline int parseInt( const char* aExpected ) throw( PARSE_ERROR )
return parseInt(); {
} NeedNUMBER( aExpected );
return parseInt();
inline int parseHex() throw( PARSE_ERROR ) }
{
NeedSYMBOLorNUMBER(); inline int parseHex() throw( PARSE_ERROR )
return (int)strtol( CurText(), NULL, 16 ); {
} NeedSYMBOLorNUMBER();
return (int)strtol( CurText(), NULL, 16 );
bool parseBool() throw( PARSE_ERROR ); }
public: bool parseBool() throw( PARSE_ERROR );
PCB_PARSER( LINE_READER* aReader, BOARD* aBoard = NULL ) :
PCB_LEXER( aReader ), public:
m_board( aBoard ) PCB_PARSER( LINE_READER* aReader, BOARD* aBoard = NULL ) :
{ PCB_LEXER( aReader ),
} m_board( aBoard )
{
BOARD_ITEM* Parse() throw( IO_ERROR, PARSE_ERROR ); }
};
BOARD_ITEM* Parse() throw( IO_ERROR, PARSE_ERROR );
};
#endif // _PCBNEW_PARSER_H_
#endif // _PCBNEW_PARSER_H_
...@@ -120,7 +120,7 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter, ...@@ -120,7 +120,7 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter,
const char* falseStr = getTokenName( T_false ); const char* falseStr = getTokenName( T_false );
const char* trueStr = getTokenName( T_true ); const char* trueStr = getTokenName( T_true );
aFormatter->Print( aNestLevel, "(%s", getTokenName( T_pcbplotparams ) ); aFormatter->Print( aNestLevel, "(%s\n", getTokenName( T_pcbplotparams ) );
aFormatter->Print( aNestLevel+1, "(%s %ld)\n", getTokenName( T_layerselection ), aFormatter->Print( aNestLevel+1, "(%s %ld)\n", getTokenName( T_layerselection ),
layerSelection ); layerSelection );
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ), aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ),
...@@ -173,7 +173,7 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter, ...@@ -173,7 +173,7 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter,
scaleSelection ); scaleSelection );
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_outputdirectory ), aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_outputdirectory ),
aFormatter->Quotew( outputDirectory ).c_str() ); aFormatter->Quotew( outputDirectory ).c_str() );
aFormatter->Print( 0, ")\n" ); aFormatter->Print( aNestLevel, ")\n" );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment