diff --git a/change_log.txt b/change_log.txt index 004d648417..7a37a49e74 100644 --- a/change_log.txt +++ b/change_log.txt @@ -5,6 +5,17 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with email address. +2008-Mar-10 UPDATE Jean-Pierre Charras +================================================================================ ++pcbnew + Pcbnew can import footprints in gpcb format in Nelib format only + Pcbnew automatically recognizes pcbnew or gpcb format when importing a footprint. + Due to differences between pcbnew and gpcb, + only gpcb newlib files containing only one footprint (one element) are useables. + Dirty rectangle calculation debugged. + WinEDA_DrawPanel::ConvertPcbUnitsToPixelsUnits( EDA_Rect& aRect ) can be used to convert a bouding box to a clip box + (see example in deltrack.cpp) + 2008-Mar-06 UPDATE Igor Plyatov ================================================================================ +help diff --git a/common/string.cpp b/common/string.cpp index 5bcc71e827..ed9739353c 100644 --- a/common/string.cpp +++ b/common/string.cpp @@ -373,21 +373,3 @@ char* strupper( char* Text ) return Text; } - -#if 0 -/********************************/ -char* strlower( char* text ) -/********************************/ -{ - char* start = text; - - while( *text ) - { - if( *text >= 'A' && *text <= 'Z' ) - *text -= 'A' - 'a'; - text++; - } - - return start; -} -#endif diff --git a/include/drawpanel_wxstruct.h b/include/drawpanel_wxstruct.h index 1bc9e7ef10..6be949f0f8 100644 --- a/include/drawpanel_wxstruct.h +++ b/include/drawpanel_wxstruct.h @@ -95,7 +95,23 @@ public: void Process_Special_Functions( wxCommandEvent& event ); wxPoint CursorRealPosition( const wxPoint& ScreenPos ); wxPoint CursorScreenPosition(); - wxPoint GetScreenCenterRealPosition(); + + /** Function ConvertPcbUnitsToPixelsUnits + * Convert pos and size of the given EDA_Rect to pos and size in pixels, + * relative to the current draw area (origin 0,0 is the left top visible corner draw area) + * according to the current scrool and zoom + * @param aRect = the given rect + */ + void ConvertPcbUnitsToPixelsUnits( EDA_Rect & aRect); + /** Function ConvertPcbUnitsToPixelsUnits + * Convert a given wxPoint position (in internal units) to the pos in pixels, + * relative to the current draw area (origin 0,0 is the left top visible corner draw area) + * according to the current scrool and zoom + * @param aPosition = the given position + */ + void ConvertPcbUnitsToPixelsUnits( wxPoint & aPosition); + + wxPoint GetScreenCenterRealPosition( void ); void MouseToCursorSchema(); void MouseTo( const wxPoint& Mouse ); diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index f1b71445aa..22073a1b37 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -78,6 +78,7 @@ SET(PCBNEW_SRCS gen_modules_placefile.cpp gendrill.cpp globaleditpad.cpp + gpcb_exchange.cpp graphpcb.cpp hotkeys.cpp initpcb.cpp diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index e4c6d27692..ce6e7ebaef 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -765,15 +765,15 @@ int MODULE::ReadDescr( FILE* File, int* LineNum ) } } - /* Recalcul de l'encadrement */ + /* Recalculate the bounding box */ Set_Rectangle_Encadrement(); return 0; } -/****************************************************/ +/*************************************************/ void MODULE::SetPosition( const wxPoint& newpos ) -/****************************************************/ +/*************************************************/ // replace le module en position newpos { diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 1fb01a38ce..243d38bdbc 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -65,7 +65,7 @@ public: unsigned long m_Link; // variable temporaire ( pour editions, ...) long m_LastEdit_Time; // Date de la derniere modification du module (gestion de librairies) - wxString m_Path; + wxString m_Path; wxString m_Doc; // Texte de description du module wxString m_KeyWord; // Liste des mots cles relatifs au module @@ -142,6 +142,14 @@ public: int Write_3D_Descr( FILE* File ) const; int ReadDescr( FILE* File, int* LineNum = NULL ); + /** + * Function Read_GPCB_Descr + * Read a footprint description in GPCB format + * @param CmpFullFileName = Full file name (there is one footprint per file. + * this is also the footprint name + * @return bool - true if success reading else false. + */ + bool Read_GPCB_Descr(const wxString & CmpFullFileName); int Read_3D_Descr( FILE* File, int* LineNum = NULL ); /* drawing functions */ diff --git a/pcbnew/deltrack.cpp b/pcbnew/deltrack.cpp index 9d5321a07d..d6abd43e5a 100644 --- a/pcbnew/deltrack.cpp +++ b/pcbnew/deltrack.cpp @@ -32,9 +32,9 @@ TRACK* WinEDA_PcbFrame::Delete_Segment( wxDC* DC, TRACK* Track ) if( Track == NULL ) return NULL; - if( Track->GetState(DELETED) ) + if( Track->GetState( DELETED ) ) { - D(printf("WinEDA_PcbFrame::Delete_Segment(): bug deleted already deleted TRACK\n");) + D( printf( "WinEDA_PcbFrame::Delete_Segment(): bug deleted already deleted TRACK\n" ); ) return NULL; } @@ -42,7 +42,7 @@ TRACK* WinEDA_PcbFrame::Delete_Segment( wxDC* DC, TRACK* Track ) { if( g_TrackSegmentCount > 0 ) { - int previous_layer = ((PCB_SCREEN*)GetScreen())->m_Active_Layer; + int previous_layer = ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer; // effacement de la piste en cours ShowNewTrackWhenMovingCursor( DrawPanel, DC, FALSE ); @@ -83,7 +83,7 @@ TRACK* WinEDA_PcbFrame::Delete_Segment( wxDC* DC, TRACK* Track ) // Rectification couche active qui a pu changer si une via // a ete effacee - ((PCB_SCREEN*)GetScreen())->m_Active_Layer = previous_layer; + ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer = previous_layer; Affiche_Status_Box(); if( g_TwoSegmentTrackBuild ) // We must have 2 segments or more, or 0 @@ -126,41 +126,19 @@ TRACK* WinEDA_PcbFrame::Delete_Segment( wxDC* DC, TRACK* Track ) #else // redraw the area where the track was + // this rectangle is correct + EDA_Rect dirty = Track->GetBoundingBox(); - // this rectangle is corrrect - EDA_Rect dirty = Track->GetBoundingBox(); + // Convert the rect coordinates and size in pixels (make a draw clip box): + DrawPanel->ConvertPcbUnitsToPixelsUnits( dirty ); - D(printf( "dirty m_Pos=(%d, %d) m_Size=(%d, %d)\n", - dirty.m_Pos.x, dirty.m_Pos.y, dirty.m_Size.x, dirty.m_Size.y );) - - int zoom = GetZoom(); - - wxPoint drwOrig = GetScreen()->m_DrawOrg; - - dirty.m_Pos.x = (dirty.m_Pos.x - drwOrig.x) / zoom; - dirty.m_Pos.y = (dirty.m_Pos.y - drwOrig.y) / zoom; - - dirty.m_Size.x = (dirty.m_Size.x - drwOrig.x) / zoom; - dirty.m_Size.y = (dirty.m_Size.y - drwOrig.y) / zoom; - - D(printf( "dirty scaled zoom=%d m_Pos=(%d, %d) m_Size=(%d, %d) drwOrig=(%d, %d)\n", - zoom, - dirty.m_Pos.x, dirty.m_Pos.y, dirty.m_Size.x, dirty.m_Size.y, - drwOrig.x, drwOrig.y );) + // Ensure the last line and column are in the dirty rectangle after truncatures + dirty.m_Size.x += 1; dirty.m_Size.y += 1; // pass wxRect() via EDA_Rect::operator wxRect() overload wxRect dirtyR = dirty; - D(printf( "dirtyR m_Pos=(%d, %d) m_Size=(%d, %d)\n", - dirtyR.x, dirtyR.y, dirtyR.width, dirtyR.height );) - -/* The calculation for dirtyR is either wrong or the handling of the clipping - rect in OnPaint() is wrong. Enable this line instead of the Refresh() below, - then try deleting a track segment. DrawPanel->RefreshRect( dirtyR, TRUE ); -*/ - - DrawPanel->Refresh( TRUE ); #endif @@ -241,7 +219,7 @@ void WinEDA_PcbFrame::Supprime_Une_Piste( wxDC* DC, TRACK* pt_segm ) return; pt_track = Marque_Une_Piste( this, DC, pt_segm, - &nb_segm, GR_OR | GR_SURBRILL ); + &nb_segm, GR_OR | GR_SURBRILL ); if( nb_segm ) /* Il y a nb_segm segments de piste a effacer */ { @@ -249,7 +227,7 @@ void WinEDA_PcbFrame::Supprime_Une_Piste( wxDC* DC, TRACK* pt_segm ) /* Effacement flag BUSY */ Struct = pt_track;; - for( ii=0; iiPnext ) + for( ii = 0; iiPnext ) { Struct->SetState( BUSY, OFF ); } diff --git a/pcbnew/gpcb_exchange.cpp b/pcbnew/gpcb_exchange.cpp new file mode 100644 index 0000000000..70fb13c6ee --- /dev/null +++ b/pcbnew/gpcb_exchange.cpp @@ -0,0 +1,568 @@ +/****************************************************/ +/* class_module.cpp : fonctions de la classe MODULE */ +/****************************************************/ + +#include "fctsys.h" + +#include "wxstruct.h" +#include "common.h" +#include "pcbnew.h" +#include "trigo.h" + + +/* read parameters from a line, and return all params in a wxArrayString + * each param is in one wxString, and double quotes removed if exists + */ +static void Extract_Parameters( wxArrayString& param_list, char* text ); +static bool TestFlags( const wxString& flg_string, long flg_mask, const wxChar* flg_name ); + + +/**************************************************************/ +bool MODULE::Read_GPCB_Descr( const wxString& CmpFullFileName ) +/**************************************************************/ + +/** + * Function Read_GPCB_Descr + * Read a footprint description in GPCB (Newlib) format + * @param CmpFullFileName = Full file name (there is one footprint per file. + * this is also the footprint name + * @return bool - true if success reading else false. + */ + +/* a sample is + * + * Element["" "" "" "" 29000 44000 0 0 0 100 ""] + * ( + * Pad[-5000 0 -4000 0 4999 0 4999 "" "1" "square"] + * Pad[4000 0 5000 0 4999 0 4999 "" "2" "square,edge2"] + * ElementLine [8000 3000 1000 3000 199] + * ElementLine [8000 -3000 8000 3000 199] + * ElementLine [-8000 3000 -1000 3000 199] + * ElementLine [-8000 -3000 -1000 -3000 199] + * ElementLine [8000 -3000 1000 -3000 199] + * ElementLine [-8000 -3000 -8000 3000 199] + * ) + * + * Format + * Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags] + * Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags) + * Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags) + * Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags) + * Element ("Desc" "Name" TX TY TDir TScale TNFlags) + * ( + * . . . contents . . . * + * ) + * With: + * SFlags Symbolic or numeric flags, for the element as a whole. + * NFlags Numeric flags, for the element as a whole. + * Desc The description of the element. This is one of the three strings which can be + * displayed on the screen. + * Name The name of the element, usually the reference designator. + * Value The value of the element. + * MX MY The location of the element’s mark. This is the reference point for placing the element and its pins and pads. + * TX TY The upper left corner of the text (one of the three strings). + * TDir The relative direction of the text. 0 means left to right for an unrotated element, 1 means up, 2 left, 3 down. + * TScale Size of the text, as a percentage of the “default” size of of the font (the default font is about 40 mils high). Default is 100 (40 mils). + * TSFlags Symbolic or numeric flags, for the text. + * TNFlags Numeric flags, for the text. + * + * Elements may contain pins, pads, element + * + * ElementLine [X1 Y1 X2 Y2 Thickness] + * ElementLine (X1 Y1 X2 Y2 Thickness) + * + * ElementArc [X Y Width Height StartAngle DeltaAngle Thickness] + * ElementArc (X Y Width Height StartAngle DeltaAngle Thickness) + * (rotation in clockwise) + * Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags] + * Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags) + * Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags) + * Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags) + * + * Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags] + * Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags) + * Pin (aX aY Thickness Drill "Name" "Number" NFlags) + * Pin (aX aY Thickness Drill "Name" NFlags) + * Pin (aX aY Thickness "Name" NFlags) + * + * Object Flags : + * + * Note that object flags can be given numerically (like 0x0147) or symbolically (like + * "found,showname,square". Some numeric values are reused for different object types. + * The table below lists the numeric value followed by the symbolic name. + * 0x0001 pin + * If set, this object is a pin. This flag is for internal use only. + * 0x0002 via + * Likewise, for vias. + * 0x0004 found + * If set, this object has been found by FindConnection(). + * 0x0008 hole + * For pins and vias, this flag means that the pin or via is a hole without a copper + * annulus. + * 0x0010 rat + * If set for a line, indicates that this line is a rat line instead of a copper trace. + * 0x0010 pininpoly + * For pins and pads, this flag is used internally to indicate that the pin or pad + * overlaps a polygon on some layer. + * 0x0010 clearpoly + * For polygons, this flag means that pins and vias will normally clear these polygons + * (thus, thermals are required for electrical connection). When clear, polygons + * will solidly connect to pins and vias. + * 0x0010 hidename + * For elements, when set the name of the element is hidden. + * 0x0020 showname + * For elements, when set the names of pins are shown. + * 0x0020 clearline + * For lines and arcs, the line/arc will clear polygons instead of connecting to + * them. + * 0x0020 fullpoly + * For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest + * one). + * 0x0040 selected + * Set when the object is selected. + * 0x0080 onsolder + * For elements and pads, indicates that they are on the solder side + * 0x0080 auto + * For lines and vias, indicates that these were created by the autorouter. + * 0x0100 square + * For pins and pads, indicates a square (vs round) pin/pad. + * 0x0200 rubberend + * For lines, used internally for rubber band moves. + * 0x0200 warn + * For pins, vias, and pads, set to indicate a warning. + * 0x0400 usetherm + * Obsolete, indicates that pins/vias should be drawn with thermal fingers. + * 0x0400 Obsolete, old files used this to indicate lines drawn on silk. + * 0x0800 octagon + * Draw pins and vias as octagons. + * 0x1000 drc + * Set for objects that fail DRC. + * 0x2000 lock + * Set for locked objects. + * 0x4000 edge2 + * For pads, indicates that the second point is closer to the edge. For pins, indicates + * that the pin is closer to a horizontal edge and thus pinout text should be vertical. + * 0x8000 marker + * Marker used internally to avoid revisiting an object. + * 0x10000 nopaste + * For pads, set to prevent a solderpaste stencil opening for the pad. Primarily + * used for pads used as fiducials. + */ +{ + #define TEXT_DEFAULT_SIZE 400 + #define OLD_GPCB_UNIT_CONV 10 + #define NEW_GPCB_UNIT_CONV 0.1 + FILE* cmpfile; + double conv_unit = NEW_GPCB_UNIT_CONV; // GPCB unit = 0.01 mils and pcbnew 0.1 + // Old version unit = 1 mil, so conv_unit is 10 or 0.1 + bool success = true; + char Line[1024]; + int NbLine = 0; + long ibuf[100]; + EDGE_MODULE* DrawSegm, * LastModStruct = NULL; + D_PAD* LastPad = NULL, * Pad; + wxArrayString params; + int iprmcnt, icnt_max, iflgidx; + + if( ( cmpfile = wxFopen( CmpFullFileName, wxT( "rt" ) ) ) == NULL ) + return false; + + GetLine( cmpfile, Line, &NbLine ); + + params.Clear(); + Extract_Parameters( params, Line ); + + iprmcnt = 0; + icnt_max = params.GetCount(); + + if( params[iprmcnt].CmpNoCase( wxT( "Element" ) ) != 0 ) + { + fclose( cmpfile ); + return false; + } + + // Test symbol after "Element": if [ units = 0.01 mils, and if ( units = 1 mil + iprmcnt++; + if( params[iprmcnt] == wxT( "(" ) ) + conv_unit = OLD_GPCB_UNIT_CONV; + + /* Analyse first line : + * Element [element_flags, description, pcb-name, value, mark_x, mark_y, text_x, text_y, + * text_direction, text_scale, text_flags] + */ + + // Read flags (unused) + iprmcnt++; + + // Read description + iprmcnt++; + m_Doc = params[iprmcnt]; + + // Read pcb-name (unused ) + iprmcnt++; + + // Read value + iprmcnt++; + m_Value->m_Text = params[iprmcnt]; + + iprmcnt++; + + // Read other infos + for( int ii = 0; ii < 6; ii++ ) + { + if( iprmcnt < icnt_max ) + { + success = false; + ibuf[ii] = 0; + } + else + params[iprmcnt].ToLong( &ibuf[ii] ); + iprmcnt++; + } + + m_Reference->m_Pos.x = (int) round( ibuf[2] * conv_unit ); + m_Reference->m_Pos.y = (int) round( ibuf[3] * conv_unit );; + m_Reference->m_Orient = ibuf[4] * 900; + + // Calculate size: default is 40 mils (400 pcb units) + // real size is: default * ibuf[5] / 100 (size in gpcb is given in percent of defalut size + ibuf[5] *= TEXT_DEFAULT_SIZE; ibuf[5] /= 100; + m_Reference->m_Size.x = m_Reference->m_Size.y = max( 20, ibuf[5] ); + m_Reference->m_Width = m_Reference->m_Size.x / 10; + m_Value->m_Orient = m_Reference->m_Orient; + m_Value->m_Size = m_Reference->m_Size; + m_Value->m_Width = m_Reference->m_Width; + + while( GetLine( cmpfile, Line, &NbLine, sizeof(Line) - 1 ) != NULL ) + { + params.Clear(); + Extract_Parameters( params, Line ); + if( params.GetCount() > 3 ) // Test units value for a string line param (more than 3 params : ident [ xx ] ) + { + if( params[1] == wxT( "(" ) ) + conv_unit = OLD_GPCB_UNIT_CONV; + else + conv_unit = NEW_GPCB_UNIT_CONV; + } + + if( params[0].CmpNoCase( wxT( "ElementLine" ) ) == 0 ) // line descr + { // Format: ElementLine [X1 Y1 X2 Y2 Thickness] + DrawSegm = new EDGE_MODULE( this ); + DrawSegm->SetLayer( SILKSCREEN_N_CMP ); + DrawSegm->m_Shape = S_SEGMENT; + + if( LastModStruct == NULL ) + { + DrawSegm->Pback = this; + m_Drawings = DrawSegm; + } + else + { + DrawSegm->Pback = LastModStruct; + LastModStruct->Pnext = DrawSegm; + } + int* list[5] = { + &DrawSegm->m_Start0.x, &DrawSegm->m_Start0.y, + &DrawSegm->m_End0.x, &DrawSegm->m_End0.y, + &DrawSegm->m_Width + }; + for( unsigned ii = 0; ii < 5; ii++ ) + { + long dim; + if( ii < (params.GetCount() - 2) ) + { + if( params[ii + 2].ToLong( &dim ) ) + *list[ii] = (int) round( dim * conv_unit ); + } + } + + DrawSegm->SetDrawCoord(); + LastModStruct = DrawSegm; + continue; + } + + if( params[0].CmpNoCase( wxT( "ElementArc" ) ) == 0 ) // Arc descr + { // format: ElementArc [X Y Width Height StartAngle DeltaAngle Thickness] + // pcbnew does know ellipse so we must have Width = Height + DrawSegm = new EDGE_MODULE( this ); + DrawSegm->SetLayer( SILKSCREEN_N_CMP ); + DrawSegm->m_Shape = S_ARC; + + if( LastModStruct == NULL ) + { + DrawSegm->Pback = this; + m_Drawings = DrawSegm; + } + else + { + DrawSegm->Pback = LastModStruct; + LastModStruct->Pnext = DrawSegm; + } + for( unsigned ii = 0; ii < 7; ii++ ) + { + long dim; + if( ii < (params.GetCount() - 2) ) + { + if( params[ii + 2].ToLong( &dim ) ) + ibuf[ii] = dim; + else + ibuf[ii] = 0; + } + else + ibuf[ii] = 0; + } + + int rayon = (ibuf[2] + ibuf[3]) / 4; // for and arc: ibuf[3] = ibuf[4]. pcbnew does not know ellipses + wxPoint centre; + centre.x = (int) round( ibuf[0] * conv_unit ); + centre.y = (int) round( ibuf[1] * conv_unit ); + DrawSegm->m_Start0 = centre; + int start_angle = ibuf[4] * 10; // Pcbnew uses 0.1 degrees as units + start_angle -= 1800; // Use normal X axis as reference + DrawSegm->m_Angle = ibuf[5] * 10; // Angle value is clockwise in gpcb and pcbnew + DrawSegm->m_End0.x = (int) round( rayon * conv_unit ); + DrawSegm->m_End0.y = 0; + RotatePoint( &DrawSegm->m_End0, -start_angle ); // Calculate start point coordinate of arc + DrawSegm->m_End0 += centre; + + DrawSegm->m_Width = (int) round( ibuf[6] * conv_unit ); + DrawSegm->SetDrawCoord(); + LastModStruct = DrawSegm; + continue; + } + + if( params[0].CmpNoCase( wxT( "Pad" ) ) == 0 ) // Pad with no hole (smd pad) + { // format: Pad [x1 y1 x2 y2 thickness clearance mask "name" "pad_number" flags] + Pad = new D_PAD( this ); + Pad->m_PadShape = PAD_RECT; + Pad->m_Masque_Layer = CMP_LAYER | SOLDERMASK_LAYER_CMP | SOLDERPASTE_LAYER_CMP; + + // Set shape from flags + iflgidx = params.GetCount() - 2; + if( TestFlags( params[iflgidx], 0x0080, wxT( "onsolder" ) ) ) + Pad->m_Masque_Layer = CUIVRE_LAYER | SOLDERMASK_LAYER_CU | SOLDERPASTE_LAYER_CU; + + for( unsigned ii = 0; ii < 5; ii++ ) + { + if( ii < params.GetCount() - 2 ) + { + long dim; + if( params[ii + 2].ToLong( &dim ) ) + ibuf[ii] = (int) round( dim * conv_unit ); + } + else + ibuf[ii] = 0; + } + + // Read name: + // Currently unused + + // Read pad number: + if( params.GetCount() > 10 ) + { + strncpy( Pad->m_Padname, CONV_TO_UTF8( params[10] ), 4 ); + } + Pad->m_Pos.x = (ibuf[0] + ibuf[2]) / 2; + Pad->m_Pos.y = (ibuf[1] + ibuf[3]) / 2; + Pad->m_Size.x = ibuf[4] + abs( ibuf[0] - ibuf[2] ); + Pad->m_Size.y = ibuf[4] + abs( ibuf[1] - ibuf[3] ); + Pad->m_Pos.x += m_Pos.x; + Pad->m_Pos.y += m_Pos.y; + if( !TestFlags( params[iflgidx], 0x0100, wxT( "square" ) ) ) + { + if( Pad->m_Size.x == Pad->m_Size.y ) + Pad->m_PadShape = PAD_ROUND; + else + Pad->m_PadShape = PAD_OVAL; + } + + + if( LastPad == NULL ) + { + Pad->Pback = (EDA_BaseStruct*) this; + m_Pads = Pad; + } + else + { + Pad->Pback = (EDA_BaseStruct*) LastPad; + LastPad->Pnext = (EDA_BaseStruct*) Pad; + } + LastPad = Pad; + continue; + } + + if( params[0].CmpNoCase( wxT( "Pin" ) ) == 0 ) // Pad with hole (trough pad) + { // format: Pin[x y Thickness Clearance Mask DrillHole Name Number Flags] + Pad = new D_PAD( this ); + Pad->m_PadShape = PAD_ROUND; + Pad->m_Masque_Layer = ALL_CU_LAYERS | + SILKSCREEN_LAYER_CMP | + SOLDERMASK_LAYER_CMP | + SOLDERMASK_LAYER_CU; + iflgidx = params.GetCount() - 2; + if( TestFlags( params[iflgidx], 0x0100, wxT( "square" ) ) ) + Pad->m_PadShape = PAD_RECT; + for( unsigned ii = 0; ii < 6; ii++ ) + { + if( ii < params.GetCount() - 2 ) + { + long dim; + if( params[ii + 2].ToLong( &dim ) ) + ibuf[ii] = (int) round( dim * conv_unit ); + } + else + ibuf[ii] = 0; + } + + // Read name: + // Currently unused + + // Read pad number: + if( params.GetCount() > 9 ) + { + strncpy( Pad->m_Padname, CONV_TO_UTF8( params[9] ), 4 ); + } + Pad->m_Pos.x = ibuf[0]; + Pad->m_Pos.y = ibuf[1]; + Pad->m_Drill.x = Pad->m_Drill.y = ibuf[5]; + Pad->m_Size.x = Pad->m_Size.y = ibuf[3] + Pad->m_Drill.x; + Pad->m_Pos.x += m_Pos.x; + Pad->m_Pos.y += m_Pos.y; + if( (Pad->m_PadShape == PAD_ROUND) && (Pad->m_Size.x != Pad->m_Size.y) ) + Pad->m_PadShape = PAD_OVAL; + + if( LastPad == NULL ) + { + Pad->Pback = (EDA_BaseStruct*) this; + m_Pads = Pad; + } + else + { + Pad->Pback = (EDA_BaseStruct*) LastPad; + LastPad->Pnext = (EDA_BaseStruct*) Pad; + } + LastPad = Pad; + continue; + } + } + + fclose( cmpfile ); + + if( m_Value->m_Text.IsEmpty() ) + m_Value->m_Text = wxT( "Val**" ); + if( m_Reference->m_Text.IsEmpty() ) + { + wxFileName filename( CmpFullFileName ); + m_Reference->m_Text = filename.GetName(); + } + + /* Recalculate the bounding box */ + Set_Rectangle_Encadrement(); + return success; +} + + +/***********************************************************************/ +static void Extract_Parameters( wxArrayString& param_list, char* text ) +/***********************************************************************/ + +/* Read a text line and extract params and tokens. + * special chars are: + * [ ] ( ) Begin and end of parameter list and units indicator + * " is a string delimiter + * space is the param separator + * The first word is the keyword + * the second item is one of ( ot [ + * other are parameters (number or delimited string) + * last parameter is ) or ] + */ +{ + int key; + wxString tmp; + + while( *text != 0 ) + { + key = *text; + text++; + + switch( key ) + { + case '[': + case ']': + case '(': + case ')': + if( !tmp.IsEmpty() ) + { + param_list.Add( tmp ); + tmp.Clear(); + } + tmp.Append( key ); + param_list.Add( tmp ); + tmp.Clear(); + break; + + case '\n': + case '\r': + case '\t': + case ' ': + if( !tmp.IsEmpty() ) + { + param_list.Add( tmp ); + tmp.Clear(); + } + break; + + case '"': + while( *text != 0 ) + { + key = *text; + text++; + if( key == '"' ) + { + param_list.Add( tmp ); + tmp.Clear(); + break; + } + else + tmp.Append( key ); + } + + break; + + default: + tmp.Append( key ); + break; + } + } +} + + +/***********************************************************************************/ +bool TestFlags( const wxString& flg_string, long flg_mask, const wxChar* flg_name ) +/***********************************************************************************/ + +/** Function TestFlags + * Test flag flg_mask or flg_name. + * @param flg_string = flsg list to test: can be a bit field flag or a list name flsg + * a bit field flag is an hexadecimal value: Ox00020000 + * a list name flsg is a string list of flags, comma separated like square,option1 + * @param flg_mask = flsg list to test + * @param flg_mask = flsg list to test + * @return true if found + */ +{ + wxString strnumber; + + if( flg_string.StartsWith( wxT( "0x" ), + &strnumber ) || flg_string.StartsWith( wxT( "0X" ), &strnumber ) ) + { + long lflags; + if( strnumber.ToLong( &lflags, 16 ) ) + if( lflags & flg_mask ) + return true; + } + else if( flg_string.Contains( flg_name ) ) + return true; + + return false; +} diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index ef9c380c75..2800e4e37b 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -43,13 +43,15 @@ MODULE* WinEDA_ModuleEditFrame::Import_Module( wxDC* DC ) wxString CmpFullFileName; FILE* dest; MODULE* module = NULL; + bool Footprint_Is_GPCB_Format = false; + wxString mask = wxT("*.*;"); mask += EXT_CMP_MASK; /* Lecture Fichier module */ CmpFullFileName = EDA_FileSelector( _( "Import Module:" ), wxEmptyString, /* Chemin par defaut */ wxEmptyString, /* nom fichier par defaut */ - EXT_CMP, /* extension par defaut */ - EXT_CMP_MASK, /* Masque d'affichage */ + wxEmptyString, /* extension par defaut */ + mask, /* Masque d'affichage */ this, wxFD_OPEN, TRUE @@ -70,21 +72,38 @@ MODULE* WinEDA_ModuleEditFrame::Import_Module( wxDC* DC ) GetLine( dest, Line, &NbLine ); if( strnicmp( Line, ENTETE_LIBRAIRIE, L_ENTETE_LIB ) != 0 ) { - DisplayError( this, _( "Not a module file" ) ); - return NULL; + if( strnicmp( Line, "Element", 7 ) == 0 ) + Footprint_Is_GPCB_Format = true; + else + { + fclose( dest ); + DisplayError( this, _( "Not a module file" ) ); + return NULL; + } } /* Lecture du fichier: recherche du debut de la descr module */ - while( GetLine( dest, Line, &NbLine ) != NULL ) - { - if( strnicmp( Line, "$MODULE", 7 ) == 0 ) - break; - } + if ( ! Footprint_Is_GPCB_Format ) + { + while( GetLine( dest, Line, &NbLine ) != NULL ) + { + if( strnicmp( Line, "$MODULE", 7 ) == 0 ) + break; + } + } module = new MODULE( m_Pcb ); - module->ReadDescr( dest, &NbLine ); - fclose( dest ); + if ( Footprint_Is_GPCB_Format ) + { + fclose( dest ); + module->Read_GPCB_Descr(CmpFullFileName); + } + else + { + module->ReadDescr( dest, &NbLine ); + fclose( dest ); + } /* Mise a jour du chainage */ if( m_Pcb->m_Modules ) diff --git a/pcbnew/makefile.include b/pcbnew/makefile.include index fc1c29d565..e6292f1cb0 100644 --- a/pcbnew/makefile.include +++ b/pcbnew/makefile.include @@ -116,7 +116,8 @@ OBJECTS= $(TARGET).o classpcb.o\ modedit.o\ export_gencad.o\ hotkeys.o \ - collectors.o + collectors.o\ + gpcb_exchange.o PolyLine.o: ../polygon/PolyLine.cpp ../polygon/PolyLine.h $(COMMON) diff --git a/share/drawpanel.cpp b/share/drawpanel.cpp index a752532603..f04548ffee 100644 --- a/share/drawpanel.cpp +++ b/share/drawpanel.cpp @@ -18,18 +18,18 @@ // Events used by WinEDA_DrawPanel BEGIN_EVENT_TABLE( WinEDA_DrawPanel, EDA_DRAW_PANEL ) - EVT_LEAVE_WINDOW( WinEDA_DrawPanel::OnMouseLeaving ) - EVT_MOUSE_EVENTS( WinEDA_DrawPanel::OnMouseEvent ) - EVT_CHAR( WinEDA_DrawPanel::OnKeyEvent ) - EVT_CHAR_HOOK( WinEDA_DrawPanel::OnKeyEvent ) - EVT_PAINT( WinEDA_DrawPanel::OnPaint ) - EVT_SIZE( WinEDA_DrawPanel::OnSize ) - EVT_ERASE_BACKGROUND( WinEDA_DrawPanel::OnEraseBackground ) - EVT_SCROLLWIN( WinEDA_DrawPanel::OnScroll ) - EVT_ACTIVATE( WinEDA_DrawPanel::OnActivate ) +EVT_LEAVE_WINDOW( WinEDA_DrawPanel::OnMouseLeaving ) +EVT_MOUSE_EVENTS( WinEDA_DrawPanel::OnMouseEvent ) +EVT_CHAR( WinEDA_DrawPanel::OnKeyEvent ) +EVT_CHAR_HOOK( WinEDA_DrawPanel::OnKeyEvent ) +EVT_PAINT( WinEDA_DrawPanel::OnPaint ) +EVT_SIZE( WinEDA_DrawPanel::OnSize ) +EVT_ERASE_BACKGROUND( WinEDA_DrawPanel::OnEraseBackground ) +EVT_SCROLLWIN( WinEDA_DrawPanel::OnScroll ) +EVT_ACTIVATE( WinEDA_DrawPanel::OnActivate ) - EVT_MENU_RANGE( ID_POPUP_ZOOM_START_RANGE, ID_POPUP_ZOOM_END_RANGE, - WinEDA_DrawPanel::Process_Popup_Zoom ) +EVT_MENU_RANGE( ID_POPUP_ZOOM_START_RANGE, ID_POPUP_ZOOM_END_RANGE, + WinEDA_DrawPanel::Process_Popup_Zoom ) END_EVENT_TABLE() /************************************************************************/ @@ -46,8 +46,8 @@ WinEDA_DrawPanel::WinEDA_DrawPanel( WinEDA_DrawFrame* parent, int id, m_Scroll_unit = 1; m_ScrollButt_unit = 40; SetBackgroundColour( wxColour( ColorRefs[g_DrawBgColor].m_Red, - ColorRefs[g_DrawBgColor].m_Green, - ColorRefs[g_DrawBgColor].m_Blue ) ); + ColorRefs[g_DrawBgColor].m_Green, + ColorRefs[g_DrawBgColor].m_Blue ) ); EnableScrolling( TRUE, TRUE ); m_ClipBox.SetSize( size ); m_ClipBox.SetX( 0 ); @@ -95,18 +95,18 @@ void WinEDA_DrawPanel::Trace_Curseur( wxDC* DC, int color ) int dy = m_ClipBox.GetHeight() * GetZoom(); GRLine( &m_ClipBox, DC, Cursor.x - dx, Cursor.y, - Cursor.x + dx, Cursor.y, 0, color ); // axe Y + Cursor.x + dx, Cursor.y, 0, color ); // axe Y GRLine( &m_ClipBox, DC, Cursor.x, Cursor.y - dx, - Cursor.x, Cursor.y + dy, 0, color ); // axe X + Cursor.x, Cursor.y + dy, 0, color ); // axe X } else { int len = CURSOR_SIZE * GetZoom(); GRLine( &m_ClipBox, DC, Cursor.x - len, Cursor.y, - Cursor.x + len, Cursor.y, 0, color ); + Cursor.x + len, Cursor.y, 0, color ); GRLine( &m_ClipBox, DC, Cursor.x, Cursor.y - len, - Cursor.x, Cursor.y + len, 0, color ); + Cursor.x, Cursor.y + len, 0, color ); } } @@ -266,19 +266,67 @@ bool WinEDA_DrawPanel::IsPointOnDisplay( wxPoint ref_pos ) } +/************************************************************************/ +void WinEDA_DrawPanel::ConvertPcbUnitsToPixelsUnits( EDA_Rect& aRect ) +/************************************************************************/ + +/** Function ConvertPcbUnitsToPixelsUnits + * Convert pos and size off the given EDA_Rect to pos and size in pixels, + * relative to the current draw area (origin 0,0 is the left top visible corner draw area) + * according to the current scrool and zoom + * @param aRect = the given rect + */ +{ + // Calculate the draw area origin in internal units: + wxPoint pos = aRect.GetPosition(); + + ConvertPcbUnitsToPixelsUnits( pos ); + aRect.SetOrigin( pos ); // rect origin in pixel units + aRect.m_Size.x /= GetZoom(); + aRect.m_Size.y /= GetZoom(); // size in pixel units +} + + +/***************************************************************************/ +void WinEDA_DrawPanel::ConvertPcbUnitsToPixelsUnits( wxPoint& aPosition ) +/***************************************************************************/ + +/** Function ConvertPcbUnitsToPixelsUnits + * Convert a given wxPoint position (in internal units) to the pos in pixels, + * relative to the current draw area (origin 0,0 is the left top visible corner draw area) + * according to the current scrool and zoom + * @param aPosition = the given position + */ +{ + // Calculate the draw area origin in internal units: + wxPoint drwOrig; + int x_axis_scale, y_axis_scale; + + GetViewStart( &drwOrig.x, &drwOrig.y ); // Origin in scrool units; + GetScrollPixelsPerUnit( &x_axis_scale, &y_axis_scale ); + drwOrig.x *= x_axis_scale; drwOrig.y *= y_axis_scale; // Origin in pixels units; + drwOrig.x *= GetZoom(); drwOrig.y *= GetZoom(); // Origin in internal units; + + drwOrig += GetScreen()->m_DrawOrg; // Real origin, according to the "plot" origin + + aPosition -= drwOrig; // position in internal units, relative to the visible draw area origin + + aPosition.x /= GetZoom(); + aPosition.y /= GetZoom(); // position in pixels, relative to the visible draw area origin +} + + /********************************************************/ wxPoint WinEDA_DrawPanel::CursorScreenPosition() /********************************************************/ /** CursorScreenPosition - * @return relative position in pixels of du curseur - * ( relative position = position in the panel draw area on screen ) + * @return the curseur position in pixels in the panel draw area on screen ) */ { wxPoint curpos = GetScreen()->m_Curseur; - curpos.x -= GetScreen()->m_DrawOrg.x; - curpos.y -= GetScreen()->m_DrawOrg.y; + curpos -= GetScreen()->m_DrawOrg; curpos.x /= GetZoom(); curpos.y /= GetZoom(); @@ -288,7 +336,7 @@ wxPoint WinEDA_DrawPanel::CursorScreenPosition() /*********************************************************/ -wxPoint WinEDA_DrawPanel::GetScreenCenterRealPosition() +wxPoint WinEDA_DrawPanel::GetScreenCenterRealPosition( void ) /*********************************************************/ /** Function GetScreenCenterRealPosition() @@ -435,9 +483,11 @@ void WinEDA_DrawPanel::SetBoundaryBox() */ { BASE_SCREEN* Screen = GetScreen();; - if(!Screen) return; - wxPoint org; - int ii, jj; + + if( !Screen ) + return; + wxPoint org; + int ii, jj; Screen->m_SizeVisu = GetClientSize(); GetViewStart( &org.x, &org.y ); @@ -476,8 +526,8 @@ void WinEDA_DrawPanel::EraseScreen( wxDC* DC ) { GRSetDrawMode( DC, GR_COPY ); GRSFilledRect( &m_ClipBox, DC, m_ClipBox.GetX(), m_ClipBox.GetY(), - m_ClipBox.GetRight(), m_ClipBox.GetBottom(), - g_DrawBgColor, g_DrawBgColor ); + m_ClipBox.GetRight(), m_ClipBox.GetBottom(), + g_DrawBgColor, g_DrawBgColor ); } @@ -498,31 +548,31 @@ void WinEDA_DrawPanel::OnPaint( wxPaintEvent& event ) static int counter; - wxRegion upd = GetUpdateRegion(); // get the update rect list + wxRegion upd = GetUpdateRegion(); // get the update rect list ++counter; PaintClipBox = upd.GetBox(); -#if 1 && defined(DEBUG) +#if 1 && defined (DEBUG) printf( "PaintClipBox[%d]=(%d, %d, %d, %d) org=(%d, %d) m_ClipBox=(%d, %d, %d, %d)\n", - counter, - PaintClipBox.x, - PaintClipBox.y, - PaintClipBox.width, - PaintClipBox.height, - org.x, org.y, - m_ClipBox.m_Pos.x, m_ClipBox.m_Pos.y, - m_ClipBox.m_Size.x, m_ClipBox.m_Size.y - ); + counter, + PaintClipBox.x, + PaintClipBox.y, + PaintClipBox.width, + PaintClipBox.height, + org.x, org.y, + m_ClipBox.m_Pos.x, m_ClipBox.m_Pos.y, + m_ClipBox.m_Size.x, m_ClipBox.m_Size.y + ); #endif PaintClipBox.x += org.x; PaintClipBox.y += org.y; #ifdef WX_ZOOM - m_ClipBox.m_Pos.x = PaintClipBox.x * GetZoom(); - m_ClipBox.m_Pos.y = PaintClipBox.y * GetZoom(); + m_ClipBox.m_Pos.x = PaintClipBox.x * GetZoom(); + m_ClipBox.m_Pos.y = PaintClipBox.y * GetZoom(); m_ClipBox.m_Size.x = PaintClipBox.width * GetZoom(); m_ClipBox.m_Size.y = PaintClipBox.height * GetZoom(); #else @@ -533,17 +583,17 @@ void WinEDA_DrawPanel::OnPaint( wxPaintEvent& event ) #endif -#if 1 && defined(DEBUG) +#if 1 // && defined(DEBUG) printf( "PaintClipBox[%d]=(%d, %d, %d, %d) org=(%d, %d) m_ClipBox=(%d, %d, %d, %d)\n", - counter, - PaintClipBox.x, - PaintClipBox.y, - PaintClipBox.width, - PaintClipBox.height, - org.x, org.y, - m_ClipBox.m_Pos.x, m_ClipBox.m_Pos.y, - m_ClipBox.m_Size.x, m_ClipBox.m_Size.y - ); + counter, + PaintClipBox.x, + PaintClipBox.y, + PaintClipBox.width, + PaintClipBox.height, + org.x, org.y, + m_ClipBox.m_Pos.x, m_ClipBox.m_Pos.y, + m_ClipBox.m_Size.x, m_ClipBox.m_Size.y + ); #endif @@ -557,13 +607,14 @@ void WinEDA_DrawPanel::OnPaint( wxPaintEvent& event ) event.Skip(); } + #else // old code { - wxPaintDC paintDC( this ); - EDA_Rect tmp; - wxRect PaintClipBox; - wxPoint org; + wxPaintDC paintDC( this ); + EDA_Rect tmp; + wxRect PaintClipBox; + wxPoint org; static int counter; @@ -587,11 +638,11 @@ void WinEDA_DrawPanel::OnPaint( wxPaintEvent& event ) #if 0 printf( "PaintClipBox[%d]=(%d, %d, %d, %d)\n", - counter, - PaintClipBox.x, - PaintClipBox.y, - PaintClipBox.width, - PaintClipBox.height ); + counter, + PaintClipBox.x, + PaintClipBox.y, + PaintClipBox.width, + PaintClipBox.height ); #endif #ifdef WX_ZOOM @@ -658,8 +709,8 @@ void WinEDA_DrawPanel::ReDraw( wxDC* DC, bool erasebg ) DC->SetFont( *g_StdFont ); SetBackgroundColour( wxColour( ColorRefs[g_DrawBgColor].m_Red, - ColorRefs[g_DrawBgColor].m_Green, - ColorRefs[g_DrawBgColor].m_Blue ) ); + ColorRefs[g_DrawBgColor].m_Green, + ColorRefs[g_DrawBgColor].m_Blue ) ); GRResetPenAndBrush( DC ); @@ -779,11 +830,11 @@ void WinEDA_DrawPanel::DrawBackGround( wxDC* DC ) { /* Draw the Y axis */ GRDashedLine( &m_ClipBox, DC, 0, -screen->ReturnPageSize().y, - 0, screen->ReturnPageSize().y, 0, Color ); + 0, screen->ReturnPageSize().y, 0, Color ); /* Draw the X axis */ GRDashedLine( &m_ClipBox, DC, -screen->ReturnPageSize().x, 0, - screen->ReturnPageSize().x, 0, 0, Color ); + screen->ReturnPageSize().x, 0, 0, Color ); } /* Draw auxiliary axis */ @@ -814,15 +865,15 @@ void WinEDA_DrawPanel::m_Draw_Auxiliary_Axis( wxDC* DC, int drawmode ) /* Draw the Y axis */ GRDashedLine( &m_ClipBox, DC, - m_Parent->m_Auxiliary_Axis_Position.x, -screen->ReturnPageSize().y, - m_Parent->m_Auxiliary_Axis_Position.x, screen->ReturnPageSize().y, - 0, Color ); + m_Parent->m_Auxiliary_Axis_Position.x, -screen->ReturnPageSize().y, + m_Parent->m_Auxiliary_Axis_Position.x, screen->ReturnPageSize().y, + 0, Color ); /* Draw the X axis */ GRDashedLine( &m_ClipBox, DC, - -screen->ReturnPageSize().x, m_Parent->m_Auxiliary_Axis_Position.y, - screen->ReturnPageSize().x, m_Parent->m_Auxiliary_Axis_Position.y, - 0, Color ); + -screen->ReturnPageSize().x, m_Parent->m_Auxiliary_Axis_Position.y, + screen->ReturnPageSize().x, m_Parent->m_Auxiliary_Axis_Position.y, + 0, Color ); } @@ -886,11 +937,12 @@ void WinEDA_DrawPanel::OnMouseEvent( wxMouseEvent& event ) static WinEDA_DrawPanel* LastPanel; static bool IgnoreNextLeftButtonRelease = false; - if(!screen) return; + if( !screen ) + return; #define MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND 5 /* Adjust value to filter mouse deplacement before - * consider the drag mouse is really a drag command, not just a movement while click - */ - static int MinDragEventCount; /* counts the drag events. + * consider the drag mouse is really a drag command, not just a movement while click + */ + static int MinDragEventCount; /* counts the drag events. * used to filter mouse moves before starting a block command * a block comman can be started only if MinDragEventCount > MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND * in order to avoid spurious block commands @@ -1153,7 +1205,7 @@ void WinEDA_DrawPanel::OnMouseEvent( wxMouseEvent& event ) #if 0 wxString msg_debug; msg_debug.Printf( " block state %d, cmd %d", - screen->BlockLocate.m_State, screen->BlockLocate.m_Command ); + screen->BlockLocate.m_State, screen->BlockLocate.m_Command ); m_Parent->PrintMsg( msg_debug ); #endif @@ -1194,7 +1246,7 @@ void WinEDA_DrawPanel::OnKeyEvent( wxKeyEvent& event ) if( event.ShiftDown() && (key > 256) ) localkey |= GR_KB_SHIFT; - wxClientDC DC( this ); + wxClientDC DC( this ); BASE_SCREEN* Screen = GetScreen(); PrepareGraphicContext( &DC );