From 9ec8d53604fb1dc64f2821c3df1937dcbde52f2e Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 15 Oct 2010 20:59:26 +0200 Subject: [PATCH] Gerbview: Added support for gerber command SR (Step and Repeat) and multiple MOIN and MOMM in file --- CHANGELOG.txt | 7 + common/common.cpp | 1 - eeschema/eeschema.cpp | 2 - gerbview/CMakeLists.txt | 1 + gerbview/block.cpp | 6 +- gerbview/class_GERBER.cpp | 42 ++++ gerbview/class_GERBER.h | 27 +- gerbview/class_aperture_macro.cpp | 22 +- gerbview/class_aperture_macro.h | 5 +- gerbview/class_gerber_draw_item.cpp | 17 +- gerbview/class_gerber_draw_item.h | 11 +- .../test-layer-mixed_units_mode.gbr | 68 +++++ .../test-layer-step-and_repeat-cross.gbr | 17 ++ .../test-layer-step-and_repeat-polygon.gbr | 18 ++ gerbview/readgerb.cpp | 8 +- gerbview/rs274_read_XY_and_IJ_coordinates.cpp | 203 +++++++++++++++ gerbview/rs274d.cpp | 235 ++---------------- gerbview/rs274x.cpp | 46 +++- include/common.h | 1 - 19 files changed, 484 insertions(+), 253 deletions(-) create mode 100644 gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr create mode 100644 gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr create mode 100644 gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr create mode 100644 gerbview/rs274_read_XY_and_IJ_coordinates.cpp diff --git a/CHANGELOG.txt b/CHANGELOG.txt index fe5f00fdcc..bced7b235d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,13 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. +2010-oct-15, UPDATE Jean-Pierre Charras +================================================================================ +++gerbview: + Added support for gerber commands: + SR (Step and Repeat) + multiple MOIN and/or MOMM in file (switch units from inch to mm and mm to inch) + 2010-oct-09, UPDATE Jean-Pierre Charras ================================================================================ ++gerbview: diff --git a/common/common.cpp b/common/common.cpp index e0b0d27b6e..d925c05d60 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -73,7 +73,6 @@ const wxString AllFilesWildcard( _( "All files (*)|*" ) ); wxString g_ProductName = wxT( "KiCad E.D.A. " ); bool g_ShowPageLimits = true; wxString g_UserLibDirBuffer; -int g_DebugLevel; int g_MouseOldButtons; int g_KeyPressed; diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index 025767c1da..6a13d93884 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -127,8 +127,6 @@ bool WinEDA_App::OnInit() wxFileName filename; WinEDA_SchematicFrame* frame = NULL; - g_DebugLevel = 0; // Debug level */ - InitEDA_Appl( wxT( "EESchema" ), APP_TYPE_EESCHEMA ); if( m_Checker && m_Checker->IsAnotherRunning() ) diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt index 8e4926cab0..86f28c2b6f 100644 --- a/gerbview/CMakeLists.txt +++ b/gerbview/CMakeLists.txt @@ -42,6 +42,7 @@ set(GERBVIEW_SRCS options.cpp pcbplot.cpp readgerb.cpp + rs274_read_XY_and_IJ_coordinates.cpp rs274d.cpp rs274x.cpp select_layers_to_pcb.cpp diff --git a/gerbview/block.cpp b/gerbview/block.cpp index bff0cc2ac3..ccb08f1053 100644 --- a/gerbview/block.cpp +++ b/gerbview/block.cpp @@ -322,7 +322,7 @@ void WinEDA_GerberFrame::Block_Move( wxDC* DC ) { GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item; if( gerb_item->HitTest( GetScreen()->m_BlockLocate ) ) - gerb_item->Move( delta ); + gerb_item->MoveAB( delta ); } DrawPanel->Refresh( TRUE ); @@ -355,8 +355,8 @@ void WinEDA_GerberFrame::Block_Duplicate( wxDC* DC ) if( gerb_item->HitTest( GetScreen()->m_BlockLocate ) ) { /* this item must be duplicated */ - BOARD_ITEM* new_item = gerb_item->Copy(); - new_item->Move( delta ); + GERBER_DRAW_ITEM* new_item = gerb_item->Copy(); + new_item->MoveAB( delta ); GetBoard()->m_Drawings.PushFront( new_item ); } } diff --git a/gerbview/class_GERBER.cpp b/gerbview/class_GERBER.cpp index 0540656ac1..d2dd83f542 100644 --- a/gerbview/class_GERBER.cpp +++ b/gerbview/class_GERBER.cpp @@ -35,6 +35,13 @@ #include "gerbview.h" #include "class_GERBER.h" + +/** + * Function scale + * converts a distance given in floating point to our deci-mils + */ +extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp + /* Format Gerber: NOTES: * Tools and D_CODES * tool number (identification of shapes) @@ -133,6 +140,10 @@ void GERBER::ResetDefaultValues() m_ImageOffset.x = m_ImageOffset.y = 0; // Coord Offset, from IO command m_Offset.x = m_Offset.y = 0; // Coord Offset, from OF command m_Rotation = 0; // Allowed 0, 90, 180, 270 + m_StepForRepeat.x = m_StepForRepeat.y = 0; // X and Y offsets for Step and Repeat command + m_XRepeatCount = 1; // The repeat count on X axis + m_YRepeatCount = 1; // The repeat count on Y axis + m_StepForRepeatMetric = false; // false = Inches, true = metric m_Has_DCode = false; // true = DCodes in file // false = no DCode-> // search for separate DCode file @@ -210,3 +221,34 @@ void GERBER::ClearMessageList() { m_Parent->ClearMessageList(); } + +/** Function StepAndRepeatItem + * Gerber format has a command Step an Repeat + * This function must be called when reading a gerber file and + * after creating a new gerber item that must be repeated + * (i.e when m_XRepeatCount or m_YRepeatCount are > 1) + * @param aItem = the item to repeat + */ +void GERBER::StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem ) +{ + if( m_XRepeatCount < 2 && m_YRepeatCount < 2 ) + return; // Nothing to repeat + // Duplicate item: +wxString msg; + for( int ii = 0; ii < m_XRepeatCount; ii++ ) + { + for( int jj = 0; jj < m_YRepeatCount; jj++ ) + { + // the first gerber item already exists (this is the template) + // create duplicate only if ii or jj > 0 + if( jj == 0 && ii == 0 ) + continue; + GERBER_DRAW_ITEM* dupItem = new GERBER_DRAW_ITEM( aItem ); + wxPoint move_vector; + move_vector.x = scale( ii * m_StepForRepeat.x, m_StepForRepeatMetric ); + move_vector.y = scale( jj * m_StepForRepeat.y, m_StepForRepeatMetric ); + dupItem->MoveXY(move_vector); + m_Parent->GetBoard()->m_Drawings.Append( dupItem ); + } + } +} diff --git a/gerbview/class_GERBER.h b/gerbview/class_GERBER.h index cd9b39d29f..98dd748112 100644 --- a/gerbview/class_GERBER.h +++ b/gerbview/class_GERBER.h @@ -12,6 +12,10 @@ #include "class_gerber_draw_item.h" #include "class_aperture_macro.h" +// An useful macro used when reading gerber files; +#define IsNumber( x ) ( ( ( (x) >= '0' ) && ( (x) <='9' ) ) \ + || ( (x) == '-' ) || ( (x) == '+' ) || ( (x) == '.' ) ) + class WinEDA_GerberFrame; class BOARD; class D_CODE; @@ -49,6 +53,14 @@ public: wxRealPoint m_LayerScale; // scale (X and Y) of layer. int m_Rotation; // Image rotation (0, 90, 180, 270 // Note these values are stored in 0.1 degrees + wxRealPoint m_StepForRepeat; // X and Y offsets for Step and Repeat command + int m_XRepeatCount; // The repeat count on X axis + int m_YRepeatCount; // The repeat count on Y axis + bool m_StepForRepeatMetric; // false = Inches, true = metric + // needed here because repeated + // gerber items can have coordinates + // in different units than step parameters + // and the actual coordinates calculation must handle this int m_Iterpolation; // Linear, 90 arc, Circ. bool m_ImageNegative; // true = Negative image int m_Current_Tool; // Current Tool (Dcode) number selected @@ -115,15 +127,13 @@ public: // functions to execute G commands or D commands: bool Execute_G_Command( char*& text, int G_commande ); - bool Execute_DCODE_Command( WinEDA_GerberFrame* frame, - char*& text, int D_commande ); + bool Execute_DCODE_Command( char*& text, int D_commande ); /** * Function ReadRS274XCommand * reads a single RS274X command terminated with a % */ - bool ReadRS274XCommand( WinEDA_GerberFrame * frame, - char aBuff[GERBER_BUFZ], char* & text ); + bool ReadRS274XCommand( char aBuff[GERBER_BUFZ], char* & text ); /** * Function ExecuteRS274XCommand @@ -167,6 +177,15 @@ public: * not found. */ APERTURE_MACRO* FindApertureMacro( const APERTURE_MACRO& aLookup ); + + /** Function StepAndRepeatItem + * Gerber format has a command Step an Repeat + * This function must be called when reading a gerber file and + * after creating a new gerber item that must be repeated + * (i.e when m_XRepeatCount or m_YRepeatCount are > 1) + * @param aItem = the item to repeat + */ + void StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem ); }; diff --git a/gerbview/class_aperture_macro.cpp b/gerbview/class_aperture_macro.cpp index 68ef9dc6a9..efe4a4e838 100644 --- a/gerbview/class_aperture_macro.cpp +++ b/gerbview/class_aperture_macro.cpp @@ -34,12 +34,7 @@ #include "trigo.h" #include "gerbview.h" -/** helper Function mapPt - * translates a point from the aperture macro coordinate system to our - * deci-mils coordinate system. - * @return wxPoint - The gerbview coordinate system vector. - */ -extern wxPoint mapPt( double x, double y, bool isMetric ); // defined it rs274d.cpp + /** * Function scale @@ -47,6 +42,19 @@ extern wxPoint mapPt( double x, double y, bool isMetric ); // defined it rs274d */ extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp +/** + * Function mapPt + * translates a point from the aperture macro coordinate system to our + * deci-mils coordinate system. + * @return wxPoint - The gerbview coordinate system vector. + */ +static wxPoint mapPt( double x, double y, bool isMetric ) +{ + wxPoint ret( scale( x, isMetric ), scale( y, isMetric ) ); + + return ret; +} + /** * Function mapExposure @@ -130,7 +138,7 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent, wxPoint curPos = aShapePos; D_CODE* tool = aParent->GetDcodeDescr(); - bool gerberMetric = aParent->m_UnitsMetric; + bool gerberMetric = m_GerbMetric; int rotation; if( mapExposure( aParent ) == false ) { diff --git a/gerbview/class_aperture_macro.h b/gerbview/class_aperture_macro.h index dde4b72694..e91fca419a 100644 --- a/gerbview/class_aperture_macro.h +++ b/gerbview/class_aperture_macro.h @@ -69,11 +69,14 @@ public: AM_PRIMITIVE_ID primitive_id; ///< The primitive type DCODE_PARAMS params; ///< A sequence of parameters used by // the primitive + bool m_GerbMetric; // units for this primitive: + // false = Inches, true = metric public: - AM_PRIMITIVE( AM_PRIMITIVE_ID aId = AMP_UNKNOWN ) + AM_PRIMITIVE( bool aGerbMetric, AM_PRIMITIVE_ID aId = AMP_UNKNOWN ) { primitive_id = aId; + m_GerbMetric = aGerbMetric; } diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index 45430e3c63..35ca84df05 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -253,11 +253,11 @@ EDA_Rect GERBER_DRAW_ITEM::GetBoundingBox() /** - * Function Move + * Function MoveAB * move this object. * @param const wxPoint& aMoveVector - the move vector for this object, in AB plotter axis. */ -void GERBER_DRAW_ITEM::Move( const wxPoint& aMoveVector ) +void GERBER_DRAW_ITEM::MoveAB( const wxPoint& aMoveVector ) { wxPoint xymove = GetXYPosition( aMoveVector ); m_Start += xymove; @@ -267,6 +267,19 @@ void GERBER_DRAW_ITEM::Move( const wxPoint& aMoveVector ) m_PolyCorners[ii] += xymove; } +/** + * Function MoveXY + * move this object. + * @param const wxPoint& aMoveVector - the move vector for this object, in XY gerber axis. + */ +void GERBER_DRAW_ITEM::MoveXY( const wxPoint& aMoveVector ) +{ + m_Start += aMoveVector; + m_End += aMoveVector; + m_ArcCentre += aMoveVector; + for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ ) + m_PolyCorners[ii] += aMoveVector; +} /** function Save. * currently: no nothing, but must be defined to meet requirements diff --git a/gerbview/class_gerber_draw_item.h b/gerbview/class_gerber_draw_item.h index a8c8b9b8c3..8415ab15d1 100644 --- a/gerbview/class_gerber_draw_item.h +++ b/gerbview/class_gerber_draw_item.h @@ -126,11 +126,18 @@ public: void SetLayerParameters( ); /** - * Function Move + * Function MoveAB * move this object. * @param const wxPoint& aMoveVector - the move vector for this object. */ - void Move( const wxPoint& aMoveVector ); + void MoveAB( const wxPoint& aMoveVector ); + + /** + * Function MoveXY + * move this object. + * @param const wxPoint& aMoveVector - the move vector for this object, in XY gerber axis. + */ + void MoveXY( const wxPoint& aMoveVector ); /** * Function GetPosition diff --git a/gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr b/gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr new file mode 100644 index 0000000000..95b855502a --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr @@ -0,0 +1,68 @@ +G04 Test handling of unit changes within a RS274X file * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +G04 Aperture 10 should be in Inches * +%ADD10C,0.050*% +%MOMM*% +G04 Aperture 11 should be in MMs * +%ADD11C,1.250*% +G04 Aperture 12 should be in MMs * +%AMTHERMAL* +7,0,0,25.4,12.7,2.54,0*% +%MOIN*% +G04 Aperture 13 is in inches * +%AMTHERMALTWO* +7,0,0,1,0.5,0.1,0*% +%MOMM*% +%ADD12THERMAL*% +%MOIN*% +%ADD13THERMALTWO*% + +%MOIN*% +G04 Box 1, using aperture 10* +X0Y0D02* +G54D10* +X0Y0D01* +X1000D01* +Y1000D01* +X0D01* +Y0D01* + +G04 Box 2, using aperture 11* +X2000Y0D02* +G54D11* +X2000Y0D01* +X3000D01* +Y1000D01* +X2000D01* +Y0D01* + +%MOMM*% +G04 Box 3, using aperture 10* +X100000Y0D02* +G54D10* +X100000Y0D01* +X125000D01* +Y25000D01* +X100000D01* +Y0D01* + +G04 Draw Thermal in box 1* +G54D12* +Y12000X12700D03* + +G04 Draw Thermal in box 2* +G04 ..switch to inches for coordinates* +G70* +Y500X2500D02* +G54D12* +Y500X2500D03* + +G04 ..switch to mms for coordinates* +G71* +G04 Draw Thermal in box 3* +G54D13* +Y12000X112000D03* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr b/gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr new file mode 100644 index 0000000000..4f693910a3 --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr @@ -0,0 +1,17 @@ +G04 Test step and repeat 1* +G04 Repeat a crosshair 3 times in the x direction and 2 times in the Y * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%SRX3Y2I5.0J2*% +%ADD10C,0.050*% + +G04 Draw crosshairs * +X-1000Y0D02* +G54D10* +X1000Y0D01* +X0Y-1000D02* +G54D10* +X0Y1000D01* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr b/gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr new file mode 100644 index 0000000000..392036fa83 --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr @@ -0,0 +1,18 @@ +G04 Test step and repeat 1* +G04 Repeat a crosshair 3 times in the x direction and 2 times in the Y * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%SRX3Y2I1J1*% +%ADD10C,0.050*% + +G04 Draw a simple square* +G36* +G01X00400Y0D02* +X00600Y0D01* +X00600Y00200D01* +X00400Y00200D01* +X00400Y0D01* +G37* + +M02* diff --git a/gerbview/readgerb.cpp b/gerbview/readgerb.cpp index 6298205fe9..c2904b86d3 100644 --- a/gerbview/readgerb.cpp +++ b/gerbview/readgerb.cpp @@ -106,7 +106,7 @@ bool WinEDA_GerberFrame::Read_GERBER_File( const wxString& GERBER_FullFileName, case 'D': /* Line type Dxx : Tool selection (xx > 0) or * command if xx = 0..9 */ D_commande = gerber->ReturnDCodeNumber( text ); - gerber->Execute_DCODE_Command( this, text, D_commande ); + gerber->Execute_DCODE_Command( text, D_commande ); break; case 'X': @@ -114,7 +114,7 @@ bool WinEDA_GerberFrame::Read_GERBER_File( const wxString& GERBER_FullFileName, gerber->m_CurrentPos = gerber->ReadXYCoord( text ); if( *text == '*' ) // command like X12550Y19250* { - gerber->Execute_DCODE_Command( this, text, + gerber->Execute_DCODE_Command( text, gerber->m_Last_Pen_Command ); } break; @@ -124,7 +124,7 @@ bool WinEDA_GerberFrame::Read_GERBER_File( const wxString& GERBER_FullFileName, gerber->m_IJPos = gerber->ReadIJCoord( text ); if( *text == '*' ) // command like X35142Y15945J504* { - gerber->Execute_DCODE_Command( this, text, + gerber->Execute_DCODE_Command( text, gerber->m_Last_Pen_Command ); } break; @@ -133,7 +133,7 @@ bool WinEDA_GerberFrame::Read_GERBER_File( const wxString& GERBER_FullFileName, if( gerber->m_CommandState != ENTER_RS274X_CMD ) { gerber->m_CommandState = ENTER_RS274X_CMD; - gerber->ReadRS274XCommand( this, line, text ); + gerber->ReadRS274XCommand( line, text ); } else //Error { diff --git a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp new file mode 100644 index 0000000000..b7f1d7916a --- /dev/null +++ b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp @@ -0,0 +1,203 @@ +/**********************************************/ +/**** rs274_read_XY_and_IJ_coordinates.cpp ****/ +/**********************************************/ + +#include "fctsys.h" +#include "common.h" + +#include "gerbview.h" +#include "macros.h" +#include "class_GERBER.h" + + +/* These routines read the text string point from Text. + * After use, advanced Text the beginning of the sequence unread + */ +wxPoint GERBER::ReadXYCoord( char*& Text ) +{ + wxPoint pos; + int type_coord = 0, current_coord, nbdigits; + bool is_float = false; + char* text; + char line[256]; + + + if( m_Relative ) + pos.x = pos.y = 0; + else + pos = m_CurrentPos; + + if( Text == NULL ) + return pos; + + text = line; + while( *Text ) + { + if( (*Text == 'X') || (*Text == 'Y') ) + { + type_coord = *Text; + Text++; + text = line; + nbdigits = 0; + while( IsNumber( *Text ) ) + { + if( *Text == '.' ) + is_float = true; + + // count digits only (sign and decimal point are not counted) + if( (*Text >= '0') && (*Text <='9') ) + nbdigits++; + *(text++) = *(Text++); + } + + *text = 0; + if( is_float ) + { + if( m_GerbMetric ) + current_coord = wxRound( atof( line ) / 0.00254 ); + else + current_coord = wxRound( atof( line ) * PCB_INTERNAL_UNIT ); + } + else + { + int fmt_scale = (type_coord == 'X') ? m_FmtScale.x : m_FmtScale.y; + if( m_NoTrailingZeros ) + { + int min_digit = + (type_coord == 'X') ? m_FmtLen.x : m_FmtLen.y; + while( nbdigits < min_digit ) + { + *(text++) = '0'; + nbdigits++; + } + + *text = 0; + } + current_coord = atoi( line ); + double real_scale = 1.0; + double scale_list[10] = + { + 10000.0, 1000.0, 100.0, 10.0, + 1, + 0.1, 0.01, 0.001, 0.0001,0.00001 + }; + real_scale = scale_list[fmt_scale]; + + if( m_GerbMetric ) + real_scale = real_scale / 25.4; + + current_coord = wxRound( current_coord * real_scale ); + } + + if( type_coord == 'X' ) + pos.x = current_coord; + else if( type_coord == 'Y' ) + pos.y = current_coord; + + continue; + } + else + break; + } + + if( m_Relative ) + { + pos.x += m_CurrentPos.x; + pos.y += m_CurrentPos.y; + } + + m_CurrentPos = pos; + return pos; +} + + +/* Returns the current coordinate type pointed to by InnJnn Text (InnnnJmmmm) + * These coordinates are relative, so if coordinate is absent, it's value + * defaults to 0 + */ +wxPoint GERBER::ReadIJCoord( char*& Text ) +{ + wxPoint pos( 0, 0 ); + + int type_coord = 0, current_coord, nbdigits; + bool is_float = false; + char* text; + char line[256]; + + if( Text == NULL ) + return pos; + + text = line; + while( *Text ) + { + if( (*Text == 'I') || (*Text == 'J') ) + { + type_coord = *Text; + Text++; + text = line; + nbdigits = 0; + while( IsNumber( *Text ) ) + { + if( *Text == '.' ) + is_float = true; + + // count digits only (sign and decimal point are not counted) + if( (*Text >= '0') && (*Text <='9') ) + nbdigits++; + *(text++) = *(Text++); + } + + *text = 0; + if( is_float ) + { + if( m_GerbMetric ) + current_coord = wxRound( atof( line ) / 0.00254 ); + else + current_coord = wxRound( atof( line ) * PCB_INTERNAL_UNIT ); + } + else + { + int fmt_scale = + (type_coord == 'I') ? m_FmtScale.x : m_FmtScale.y; + if( m_NoTrailingZeros ) + { + int min_digit = + (type_coord == 'I') ? m_FmtLen.x : m_FmtLen.y; + while( nbdigits < min_digit ) + { + *(text++) = '0'; + nbdigits++; + } + + *text = 0; + } + current_coord = atoi( line ); + double real_scale = 1.0; + if( fmt_scale < 0 || fmt_scale > 9 ) + fmt_scale = 4; // select scale 1.0 + + double scale_list[10] = + { + 10000.0, 1000.0, 100.0, 10.0, + 1, + 0.1, 0.01, 0.001, 0.0001,0.00001 + }; + real_scale = scale_list[fmt_scale]; + + if( m_GerbMetric ) + real_scale = real_scale / 25.4; + current_coord = wxRound( current_coord * real_scale ); + } + if( type_coord == 'I' ) + pos.x = current_coord; + else if( type_coord == 'J' ) + pos.y = current_coord; + continue; + } + else + break; + } + + m_IJPos = pos; + return pos; +} diff --git a/gerbview/rs274d.cpp b/gerbview/rs274d.cpp index fa42b879a5..3854e2036e 100644 --- a/gerbview/rs274d.cpp +++ b/gerbview/rs274d.cpp @@ -3,12 +3,8 @@ /********************/ #include "fctsys.h" - -//#include "polygons_defs.h" #include "common.h" -//#include "confirm.h" -//#include "macros.h" #include "gerbview.h" #include "trigo.h" #include "macros.h" @@ -17,9 +13,6 @@ #include -#define IsNumber( x ) ( ( ( (x) >= '0' ) && ( (x) <='9' ) ) \ - || ( (x) == '-' ) || ( (x) == '+' ) || ( (x) == '.' ) ) - /* Gerber: NOTES about some important commands found in RS274D and RS274X (G codes): * Gn = * G01 linear interpolation (right trace) @@ -448,199 +441,6 @@ static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGbrItem, } -/* These routines read the text string point from Text. - * After use, advanced Text the beginning of the sequence unread - */ -wxPoint GERBER::ReadXYCoord( char*& Text ) -{ - wxPoint pos; - int type_coord = 0, current_coord, nbdigits; - bool is_float = false; - char* text; - char line[256]; - - - if( m_Relative ) - pos.x = pos.y = 0; - else - pos = m_CurrentPos; - - if( Text == NULL ) - return pos; - - text = line; - while( *Text ) - { - if( (*Text == 'X') || (*Text == 'Y') ) - { - type_coord = *Text; - Text++; - text = line; - nbdigits = 0; - while( IsNumber( *Text ) ) - { - if( *Text == '.' ) - is_float = true; - - // count digits only (sign and decimal point are not counted) - if( (*Text >= '0') && (*Text <='9') ) - nbdigits++; - *(text++) = *(Text++); - } - - *text = 0; - if( is_float ) - { - if( m_GerbMetric ) - current_coord = wxRound( atof( line ) / 0.00254 ); - else - current_coord = wxRound( atof( line ) * PCB_INTERNAL_UNIT ); - } - else - { - int fmt_scale = (type_coord == 'X') ? m_FmtScale.x : m_FmtScale.y; - if( m_NoTrailingZeros ) - { - int min_digit = - (type_coord == 'X') ? m_FmtLen.x : m_FmtLen.y; - while( nbdigits < min_digit ) - { - *(text++) = '0'; - nbdigits++; - } - - *text = 0; - } - current_coord = atoi( line ); - double real_scale = 1.0; - double scale_list[10] = - { - 10000.0, 1000.0, 100.0, 10.0, - 1, - 0.1, 0.01, 0.001, 0.0001,0.00001 - }; - real_scale = scale_list[fmt_scale]; - - if( m_GerbMetric ) - real_scale = real_scale / 25.4; - - current_coord = wxRound( current_coord * real_scale ); - } - - if( type_coord == 'X' ) - pos.x = current_coord; - else if( type_coord == 'Y' ) - pos.y = current_coord; - - continue; - } - else - break; - } - - if( m_Relative ) - { - pos.x += m_CurrentPos.x; - pos.y += m_CurrentPos.y; - } - - m_CurrentPos = pos; - return pos; -} - - -/* Returns the current coordinate type pointed to by InnJnn Text (InnnnJmmmm) - * These coordinates are relative, so if coordinate is absent, it's value - * defaults to 0 - */ -wxPoint GERBER::ReadIJCoord( char*& Text ) -{ - wxPoint pos( 0, 0 ); - - int type_coord = 0, current_coord, nbdigits; - bool is_float = false; - char* text; - char line[256]; - - if( Text == NULL ) - return pos; - - text = line; - while( *Text ) - { - if( (*Text == 'I') || (*Text == 'J') ) - { - type_coord = *Text; - Text++; - text = line; - nbdigits = 0; - while( IsNumber( *Text ) ) - { - if( *Text == '.' ) - is_float = true; - - // count digits only (sign and decimal point are not counted) - if( (*Text >= '0') && (*Text <='9') ) - nbdigits++; - *(text++) = *(Text++); - } - - *text = 0; - if( is_float ) - { - if( m_GerbMetric ) - current_coord = wxRound( atof( line ) / 0.00254 ); - else - current_coord = wxRound( atof( line ) * PCB_INTERNAL_UNIT ); - } - else - { - int fmt_scale = - (type_coord == 'I') ? m_FmtScale.x : m_FmtScale.y; - if( m_NoTrailingZeros ) - { - int min_digit = - (type_coord == 'I') ? m_FmtLen.x : m_FmtLen.y; - while( nbdigits < min_digit ) - { - *(text++) = '0'; - nbdigits++; - } - - *text = 0; - } - current_coord = atoi( line ); - double real_scale = 1.0; - if( fmt_scale < 0 || fmt_scale > 9 ) - fmt_scale = 4; // select scale 1.0 - - double scale_list[10] = - { - 10000.0, 1000.0, 100.0, 10.0, - 1, - 0.1, 0.01, 0.001, 0.0001,0.00001 - }; - real_scale = scale_list[fmt_scale]; - - if( m_GerbMetric ) - real_scale = real_scale / 25.4; - current_coord = wxRound( current_coord * real_scale ); - } - if( type_coord == 'I' ) - pos.x = current_coord; - else if( type_coord == 'J' ) - pos.y = current_coord; - continue; - } - else - break; - } - - m_IJPos = pos; - return pos; -} - - /* Read the Gnn sequence and returns the value nn. */ int GERBER::ReturnGCodeNumber( char*& Text ) @@ -770,6 +570,13 @@ bool GERBER::Execute_G_Command( char*& text, int G_commande ) break; case GC_TURN_OFF_POLY_FILL: + if( m_Exposure && m_Parent->GetBoard()->m_Drawings ) // End of polygon + { + GERBER_DRAW_ITEM * gbritem = + (GERBER_DRAW_ITEM*)( m_Parent->GetBoard()->m_Drawings.GetLast() ); + StepAndRepeatItem( *gbritem ); + } + m_Exposure = false; m_PolygonFillMode = false; m_PolygonFillModeState = 0; break; @@ -806,29 +613,15 @@ int scale( double aCoord, bool isMetric ) } -/** - * Function mapPt - * translates a point from the aperture macro coordinate system to our - * deci-mils coordinate system. - * @return wxPoint - The gerbview coordinate system vector. - */ -wxPoint mapPt( double x, double y, bool isMetric ) -{ - wxPoint ret( scale( x, isMetric ), scale( y, isMetric ) ); - - return ret; -} - - -bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int D_commande ) +bool GERBER::Execute_DCODE_Command( char*& text, int D_commande ) { wxSize size( 15, 15 ); APERTURE_T aperture = APT_CIRCLE; GERBER_DRAW_ITEM* gbritem; - BOARD* pcb = frame->GetBoard(); + BOARD* pcb = m_Parent->GetBoard(); - int activeLayer = frame->GetScreen()->m_Active_Layer; + int activeLayer = m_Parent->GetScreen()->m_Active_Layer; int dcode = 0; D_CODE* tool = NULL; @@ -915,6 +708,11 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int break; case 2: // code D2: exposure OFF (i.e. "move to") + if( m_Exposure && pcb->m_Drawings ) // End of polygon + { + gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() ); + StepAndRepeatItem( *gbritem ); + } m_Exposure = false; m_PreviousPos = m_CurrentPos; m_PolygonFillModeState = 0; @@ -950,6 +748,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int // m_CurrentPos.x, m_CurrentPos.y ); ) fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos, m_CurrentPos, size.x, m_LayerNegative, m_ImageNegative ); + StepAndRepeatItem( *gbritem ); break; case GERB_INTERPOL_LINEAR_01X: @@ -972,6 +771,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int ( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ? false : true, m_360Arc_enbl, m_LayerNegative, m_ImageNegative ); + StepAndRepeatItem( *gbritem ); break; default: @@ -1010,6 +810,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int fillFlashedGBRITEM( gbritem, aperture, dcode, activeLayer, m_CurrentPos, size, m_LayerNegative, m_ImageNegative ); + StepAndRepeatItem( *gbritem ); m_PreviousPos = m_CurrentPos; break; diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp index 8dd0cf296e..f9509b874e 100644 --- a/gerbview/rs274x.cpp +++ b/gerbview/rs274x.cpp @@ -53,7 +53,7 @@ enum RS274X_PARAMETERS { LAYER_NAME = CODE( 'L', 'N' ), // Default: Positive LAYER_POLARITY = CODE( 'L', 'P' ), KNOCKOUT = CODE( 'K', 'O' ), // Default: off - STEP_AND_REPEAT = CODE( 'S', 'P' ), // Default: A = 1, B = 1 + STEP_AND_REPEAT = CODE( 'S', 'R' ), // Default: A = 1, B = 1 ROTATE = CODE( 'R', 'O' ), // Default: 0 // Miscellaneous parameters: @@ -126,8 +126,7 @@ static double ReadDouble( char*& text ) } -bool GERBER::ReadRS274XCommand( WinEDA_GerberFrame* frame, - char buff[GERBER_BUFZ], char*& text ) +bool GERBER::ReadRS274XCommand( char buff[GERBER_BUFZ], char*& text ) { bool ok = true; int code_command; @@ -366,10 +365,43 @@ bool GERBER::ExecuteRS274XCommand( int command, ReportMessage( _( "RS274X: Command \"IR\" rotation value not allowed" ) ); break; + case STEP_AND_REPEAT: // command SR, like %SRX3Y2I5.0J2*% + m_StepForRepeat.x = m_StepForRepeat.x = 0.0; // offset for Step and Repeat command + m_XRepeatCount = m_YRepeatCount =1; // The repeat count + m_StepForRepeatMetric = m_GerbMetric; // the step units + while( *text && *text != '*' ) + { + switch( *text ) + { + case 'I': // X axis offset + text++; + m_StepForRepeat.x = ReadDouble( text ); + break; + + case 'J': // Y axis offset + text++; + m_StepForRepeat.y = ReadDouble( text ); + break; + + case 'X': // X axis repeat count + text++; + m_XRepeatCount = ReadInt( text ); + break; + + case 'Y': // Y axis offset + text++; + m_YRepeatCount = ReadInt( text ); + break; + default: + text++; + break; + } + } + break; + case IMAGE_JUSTIFY: case PLOTTER_FILM: case KNOCKOUT: - case STEP_AND_REPEAT: case ROTATE: msg.Printf( _( "RS274X: Command \"%c%c\" ignored by Gerbview" ), (command >> 8) & 0xFF, command & 0xFF ); @@ -706,12 +738,9 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ], am.name.Append( *text++ ); } - if( g_DebugLevel > 0 ) - wxMessageBox( am.name, wxT( "macro name" ) ); - for( ; ; ) { - AM_PRIMITIVE prim; + AM_PRIMITIVE prim( m_GerbMetric ); if( *text == '*' ) ++text; @@ -797,7 +826,6 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ], prim.primitive_id, i ); ReportMessage( msg ); } - // there are more parameters to read if this is an AMP_OUTLINE if( prim.primitive_id == AMP_OUTLINE ) { diff --git a/include/common.h b/include/common.h index 3df729b4af..e2dbcc35d1 100644 --- a/include/common.h +++ b/include/common.h @@ -156,7 +156,6 @@ extern wxString g_ProductName; /* Default user lib path can be left void, if the standard lib path is used */ extern wxString g_UserLibDirBuffer; -extern int g_DebugLevel; extern int g_MouseOldButtons; extern int g_KeyPressed;