From 2ce06cfe083457ebb4258df1d15b5e1c0eaa6d79 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 24 Sep 2012 18:03:03 +0200 Subject: [PATCH] Pcbnew: fix compil warning and a minor bug in plot negative (frame fer plotted in white therefore not visible). minor code cleaning --- pcbnew/CMakeLists.txt | 3 +- pcbnew/pcb_plot_params.cpp | 4 + pcbnew/pcbplot.h | 8 +- .../{plot_rtn.cpp => plot_board_layers.cpp} | 709 ++---------------- pcbnew/plot_brditems_plotter.cpp | 685 +++++++++++++++++ pcbnew/scripting/pcbnew_footprint_wizards.cpp | 134 ++-- 6 files changed, 815 insertions(+), 728 deletions(-) rename pcbnew/{plot_rtn.cpp => plot_board_layers.cpp} (51%) create mode 100644 pcbnew/plot_brditems_plotter.cpp diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 16094345f0..b7e743b01d 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -189,7 +189,8 @@ set(PCBNEW_CLASS_SRCS pcbnew.cpp pcbnew_config.cpp pcbplot.cpp - plot_rtn.cpp + plot_board_layers.cpp + plot_brditems_plotter.cpp print_board_functions.cpp printout_controler.cpp ratsnest.cpp diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp index bf84c011df..9f8e03701b 100644 --- a/pcbnew/pcb_plot_params.cpp +++ b/pcbnew/pcb_plot_params.cpp @@ -145,6 +145,10 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter, m_useAuxOrigin ? trueStr : falseStr ); aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpennumber ), m_HPGLPenNum ); +// Obsolete parameter, pen speed is no more managed, because hpgl format +// is now an export format, and for this, pen speed has no meaning +// aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpenspeed ), +// m_HPGLPenSpeed ); aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpenspeed ), m_HPGLPenSpeed ); aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_hpglpendiameter ), diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index 5180704ac5..4c57dace42 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -41,11 +41,13 @@ class BOARD; // Convert pcb dimension of 0.1 mil to PS units of inches. #define SCALE_PS .0001 -// Convert dimension 0.1 mil -> HPGL units: +// Convert dimension 0.1 mil -> HPGL units (1 HPGL unit = 25 micrometers): #define SCALE_HPGL 0.102041 -// Small drill marks diameter value (in 1/10000 inch) -#define SMALL_DRILL 150 +// Small drill marks (small pad holes) diameter value +#define SMALL_DRILL (int)( 0.35 * IU_PER_MM ) + + // A helper class to plot board items class BRDITEMS_PLOTTER: public PCB_PLOT_PARAMS { diff --git a/pcbnew/plot_rtn.cpp b/pcbnew/plot_board_layers.cpp similarity index 51% rename from pcbnew/plot_rtn.cpp rename to pcbnew/plot_board_layers.cpp index 9c50ea3ebd..bf6ae6b8ff 100644 --- a/pcbnew/plot_rtn.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -1,8 +1,34 @@ /** - * @file plot_rtn.cpp - * @brief Common plot routines. + * @file plot_board_layers.cpp + * @brief Functions to plot one board layer (silkscreen layers or other layers). + * Silkscreen layers have specific requirement for pads (not filled) and texts + * (with option to remove them from some copper areas (pads...) */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * 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 write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + #include #include #include @@ -25,126 +51,9 @@ #include #include -/* Function getColor - * return the layer colorfrom the layer id - * White color is special: cannot be seen on a white paper - * and in B&W mode, is plotted as white but other colors are plotted in BLACK - * so the returned color is LIGHTGRAY when the layer color is WHITE - */ -EDA_COLOR_T BRDITEMS_PLOTTER::getColor( int aLayer ) -{ - EDA_COLOR_T color = m_board->GetLayerColor( aLayer ); - if (color == WHITE) - color = LIGHTGRAY; - return color; -} - -bool BRDITEMS_PLOTTER::PlotAllTextsModule( MODULE* aModule ) -{ - // see if we want to plot VALUE and REF fields - bool trace_val = GetPlotValue(); - bool trace_ref = GetPlotReference(); - - TEXTE_MODULE* textModule = aModule->m_Reference; - unsigned textLayer = textModule->GetLayer(); - - if( textLayer >= 32 ) - return false; - - if( ( ( 1 << textLayer ) & m_layerMask ) == 0 ) - trace_ref = false; - - if( !textModule->IsVisible() && !GetPlotInvisibleText() ) - trace_ref = false; - - textModule = aModule->m_Value; - textLayer = textModule->GetLayer(); - - if( textLayer > 32 ) - return false; - - if( ( (1 << textLayer) & m_layerMask ) == 0 ) - trace_val = false; - - if( !textModule->IsVisible() && !GetPlotInvisibleText() ) - trace_val = false; - - // Plot text fields, if allowed - if( trace_ref ) - { - if( GetReferenceColor() == UNSPECIFIED_COLOR ) - PlotTextModule( aModule->m_Reference, getColor( textLayer ) ); - else - PlotTextModule( aModule->m_Reference, GetReferenceColor() ); - } - - if( trace_val ) - { - if( GetValueColor() == UNSPECIFIED_COLOR ) - PlotTextModule( aModule->m_Value, getColor( textLayer ) ); - else - PlotTextModule( aModule->m_Value, GetValueColor() ); - } - - for( textModule = (TEXTE_MODULE*) aModule->m_Drawings.GetFirst(); - textModule != NULL; textModule = textModule->Next() ) - { - if( textModule->Type() != PCB_MODULE_TEXT_T ) - continue; - - if( !GetPlotOtherText() ) - continue; - - if( !textModule->IsVisible() && !GetPlotInvisibleText() ) - continue; - - textLayer = textModule->GetLayer(); - - if( textLayer >= 32 ) - return false; - - if( !( ( 1 << textLayer ) & m_layerMask ) ) - continue; - - PlotTextModule( textModule, getColor( textLayer ) ); - } - - return true; -} - - -// plot items like text and graphics, but not tracks and module -void BRDITEMS_PLOTTER::PlotBoardGraphicItems() -{ - for( BOARD_ITEM* item = m_board->m_Drawings; item; item = item->Next() ) - { - switch( item->Type() ) - { - case PCB_LINE_T: - PlotDrawSegment( (DRAWSEGMENT*) item); - break; - - case PCB_TEXT_T: - PlotTextePcb( (TEXTE_PCB*) item ); - break; - - case PCB_DIMENSION_T: - PlotDimension( (DIMENSION*) item ); - break; - - case PCB_TARGET_T: - PlotPcbTarget( (PCB_TARGET*) item ); - break; - - case PCB_MARKER_T: - default: - break; - } - } -} - - /* Creates the plot for silkscreen layers + * Silkscreen layers have specific requirement for pads (not filled) and texts + * (with option to remove them from some copper areas (pads...) */ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, long aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt ) @@ -252,440 +161,6 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, long aLayerMask, } } - -void BRDITEMS_PLOTTER::PlotTextModule( TEXTE_MODULE* pt_texte, - EDA_COLOR_T aColor ) -{ - wxSize size; - wxPoint pos; - int orient, thickness; - - if( aColor == WHITE ) - aColor = LIGHTGRAY; - m_plotter->SetColor( aColor ); - - // calculate some text parameters : - size = pt_texte->m_Size; - pos = pt_texte->m_Pos; - - orient = pt_texte->GetDrawRotation(); - - thickness = pt_texte->m_Thickness; - - if( GetMode() == LINE ) - thickness = -1; - - if( pt_texte->m_Mirror ) - NEGATE( size.x ); // Text is mirrored - - // Non bold texts thickness is clamped at 1/6 char size by the low level draw function. - // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size - // (like bold text) and we manage the thickness. - // So we set bold flag to true - bool allow_bold = pt_texte->m_Bold || thickness; - - m_plotter->Text( pos, aColor, - pt_texte->m_Text, - orient, size, - pt_texte->m_HJustify, pt_texte->m_VJustify, - thickness, pt_texte->m_Italic, allow_bold ); -} - - -void BRDITEMS_PLOTTER::PlotDimension( DIMENSION* aDim ) -{ - if( (GetLayerMask( aDim->GetLayer() ) & m_layerMask) == 0 ) - return; - - DRAWSEGMENT draw; - - draw.SetWidth( (GetMode() == LINE) ? -1 : aDim->GetWidth() ); - draw.SetLayer( aDim->GetLayer() ); - - EDA_COLOR_T color = aDim->GetBoard()->GetLayerColor( aDim->GetLayer() ); - // Set plot color (change WHITE to LIGHTGRAY because - // the white items are not seen on a white paper or screen - m_plotter->SetColor( color != WHITE ? color : LIGHTGRAY); - - PlotTextePcb( &aDim->m_Text ); - - draw.SetStart( wxPoint( aDim->m_crossBarOx, aDim->m_crossBarOy )); - draw.SetEnd( wxPoint( aDim->m_crossBarFx, aDim->m_crossBarFy )); - PlotDrawSegment( &draw ); - - draw.SetStart( wxPoint( aDim->m_featureLineGOx, aDim->m_featureLineGOy )); - draw.SetEnd( wxPoint( aDim->m_featureLineGFx, aDim->m_featureLineGFy )); - PlotDrawSegment( &draw ); - - draw.SetStart( wxPoint( aDim->m_featureLineDOx, aDim->m_featureLineDOy )); - draw.SetEnd( wxPoint( aDim->m_featureLineDFx, aDim->m_featureLineDFy )); - PlotDrawSegment( &draw ); - - draw.SetStart( wxPoint( aDim->m_arrowD1Ox, aDim->m_arrowD1Oy )); - draw.SetEnd( wxPoint( aDim->m_arrowD1Fx, aDim->m_arrowD1Fy )); - PlotDrawSegment( &draw ); - - draw.SetStart( wxPoint( aDim->m_arrowD2Ox, aDim->m_arrowD2Oy )); - draw.SetEnd( wxPoint( aDim->m_arrowD2Fx, aDim->m_arrowD2Fy )); - PlotDrawSegment( &draw ); - - draw.SetStart( wxPoint( aDim->m_arrowG1Ox, aDim->m_arrowG1Oy )); - draw.SetEnd( wxPoint( aDim->m_arrowG1Fx, aDim->m_arrowG1Fy )); - PlotDrawSegment( &draw ); - - draw.SetStart( wxPoint( aDim->m_arrowG2Ox, aDim->m_arrowG2Oy )); - draw.SetEnd( wxPoint( aDim->m_arrowG2Fx, aDim->m_arrowG2Fy )); - PlotDrawSegment( &draw ); -} - - -void BRDITEMS_PLOTTER::PlotPcbTarget( PCB_TARGET* aMire ) -{ - int dx1, dx2, dy1, dy2, radius; - - if( (GetLayerMask( aMire->GetLayer() ) & m_layerMask) == 0 ) - return; - - m_plotter->SetColor( getColor( aMire->GetLayer() ) ); - - DRAWSEGMENT draw; - - draw.SetShape( S_CIRCLE ); - draw.SetWidth( ( GetMode() == LINE ) ? -1 : aMire->GetWidth() ); - draw.SetLayer( aMire->GetLayer() ); - draw.SetStart( aMire->GetPosition() ); - radius = aMire->GetSize() / 3; - if( aMire->GetShape() ) // shape X - radius = aMire->GetSize() / 2; - - // Draw the circle - draw.SetEnd( wxPoint( draw.GetStart().x + radius, draw.GetStart().y )); - - PlotDrawSegment( &draw ); - - draw.SetShape( S_SEGMENT ); - - radius = aMire->GetSize() / 2; - dx1 = radius; - dy1 = 0; - dx2 = 0; - dy2 = radius; - - if( aMire->GetShape() ) // Shape X - { - dx1 = dy1 = radius; - dx2 = dx1; - dy2 = -dy1; - } - - wxPoint mirePos( aMire->GetPosition() ); - - // Draw the X or + shape: - draw.SetStart( wxPoint( mirePos.x - dx1, mirePos.y - dy1 )); - draw.SetEnd( wxPoint( mirePos.x + dx1, mirePos.y + dy1 )); - PlotDrawSegment( &draw ); - - draw.SetStart( wxPoint( mirePos.x - dx2, mirePos.y - dy2 )); - draw.SetEnd( wxPoint( mirePos.x + dx2, mirePos.y + dy2 )); - PlotDrawSegment( &draw ); -} - - -// Plot footprints graphic items (outlines) -void BRDITEMS_PLOTTER::Plot_Edges_Modules() -{ - for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) - { - for( EDGE_MODULE* edge = (EDGE_MODULE*) module->m_Drawings.GetFirst(); - edge; edge = edge->Next() ) - { - if( edge->Type() != PCB_MODULE_EDGE_T ) - continue; - - if( ( GetLayerMask( edge->GetLayer() ) & m_layerMask ) == 0 ) - continue; - - Plot_1_EdgeModule( edge ); - } - } -} - - -//* Plot a graphic item (outline) relative to a footprint -void BRDITEMS_PLOTTER::Plot_1_EdgeModule( EDGE_MODULE* aEdge ) -{ - int type_trace; // Type of item to plot. - int thickness; // Segment thickness. - int radius; // Circle radius. - - if( aEdge->Type() != PCB_MODULE_EDGE_T ) - return; - - m_plotter->SetColor( getColor( aEdge->GetLayer() ) ); - - type_trace = aEdge->GetShape(); - thickness = aEdge->GetWidth(); - - wxPoint pos( aEdge->GetStart() ); - wxPoint end( aEdge->GetEnd() ); - - switch( type_trace ) - { - case S_SEGMENT: - m_plotter->ThickSegment( pos, end, thickness, GetMode() ); - break; - - case S_CIRCLE: - radius = (int) hypot( (double) ( end.x - pos.x ), - (double) ( end.y - pos.y ) ); - m_plotter->ThickCircle( pos, radius * 2, thickness, GetMode() ); - break; - - case S_ARC: - { - radius = (int) hypot( (double) ( end.x - pos.x ), - (double) ( end.y - pos.y ) ); - - double startAngle = ArcTangente( end.y - pos.y, end.x - pos.x ); - - double endAngle = startAngle + aEdge->GetAngle(); - - if ( ( GetFormat() == PLOT_FORMAT_DXF ) && - ( m_layerMask & ( SILKSCREEN_LAYER_BACK | DRAW_LAYER | COMMENT_LAYER ) ) ) - m_plotter->ThickArc( pos, -startAngle, -endAngle, radius, - thickness, GetMode() ); - else - m_plotter->ThickArc( pos, -endAngle, -startAngle, radius, - thickness, GetMode() ); - } - break; - - case S_POLYGON: - { - const std::vector& polyPoints = aEdge->GetPolyPoints(); - - if( polyPoints.size() <= 1 ) // Malformed polygon - break; - - // We must compute true coordinates from m_PolyList - // which are relative to module position, orientation 0 - MODULE* module = aEdge->GetParentModule(); - - std::vector< wxPoint > cornerList; - - cornerList.reserve( polyPoints.size() ); - - for( unsigned ii = 0; ii < polyPoints.size(); ii++ ) - { - wxPoint corner = polyPoints[ii]; - - if( module ) - { - RotatePoint( &corner, module->GetOrientation() ); - corner += module->GetPosition(); - } - - cornerList.push_back( corner ); - } - - m_plotter->PlotPoly( cornerList, FILLED_SHAPE, thickness ); - } - break; - } -} - - -// Plot a PCB Text, i;e. a text found on a copper or technical layer -void BRDITEMS_PLOTTER::PlotTextePcb( TEXTE_PCB* pt_texte ) -{ - int orient, thickness; - wxPoint pos; - wxSize size; - - if( pt_texte->m_Text.IsEmpty() ) - return; - - if( ( GetLayerMask( pt_texte->GetLayer() ) & m_layerMask ) == 0 ) - return; - - m_plotter->SetColor( getColor( pt_texte->GetLayer() ) ); - - size = pt_texte->m_Size; - pos = pt_texte->m_Pos; - orient = pt_texte->m_Orient; - thickness = ( GetMode() == LINE ) ? -1 : pt_texte->m_Thickness; - - if( pt_texte->m_Mirror ) - size.x = -size.x; - - // Non bold texts thickness is clamped at 1/6 char size by the low level draw function. - // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size - // (like bold text) and we manage the thickness. - // So we set bold flag to true - bool allow_bold = pt_texte->m_Bold || thickness; - - if( pt_texte->m_MultilineAllowed ) - { - wxArrayString* list = wxStringSplit( pt_texte->m_Text, '\n' ); - wxPoint offset; - - offset.y = pt_texte->GetInterline(); - - RotatePoint( &offset, orient ); - - for( unsigned i = 0; i < list->Count(); i++ ) - { - wxString txt = list->Item( i ); - m_plotter->Text( pos, UNSPECIFIED_COLOR, txt, orient, size, - pt_texte->m_HJustify, pt_texte->m_VJustify, - thickness, pt_texte->m_Italic, allow_bold ); - pos += offset; - } - - delete list; - } - else - { - m_plotter->Text( pos, UNSPECIFIED_COLOR, pt_texte->m_Text, orient, size, - pt_texte->m_HJustify, pt_texte->m_VJustify, - thickness, pt_texte->m_Italic, allow_bold ); - } -} - - -/* Plot areas (given by .m_FilledPolysList member) in a zone - */ -void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) -{ - std::vector polysList = aZone->GetFilledPolysList(); - unsigned imax = polysList.size(); - - if( imax == 0 ) // Nothing to draw - return; - - // We need a buffer to store corners coordinates: - static std::vector< wxPoint > cornerList; - cornerList.clear(); - - m_plotter->SetColor( getColor( aZone->GetLayer() ) ); - - /* Plot all filled areas: filled areas have a filled area and a thick - * outline we must plot the filled area itself ( as a filled polygon - * OR a set of segments ) and plot the thick outline itself - * - * in non filled mode the outline is plotted, but not the filling items - */ - for( unsigned ic = 0; ic < imax; ic++ ) - { - CPolyPt* corner = &polysList[ic]; - cornerList.push_back( wxPoint( corner->x, corner->y) ); - - if( corner->end_contour ) // Plot the current filled area outline - { - // First, close the outline - if( cornerList[0] != cornerList[cornerList.size() - 1] ) - { - cornerList.push_back( cornerList[0] ); - } - - // Plot the current filled area and its outline - if( GetMode() == FILLED ) - { - // Plot the current filled area polygon - if( aZone->m_FillMode == 0 ) // We are using solid polygons - { // (if != 0: using segments ) - m_plotter->PlotPoly( cornerList, FILLED_SHAPE ); - } - else // We are using areas filled by - { // segments: plot them ) - for( unsigned iseg = 0; iseg < aZone->m_FillSegmList.size(); iseg++ ) - { - wxPoint start = aZone->m_FillSegmList[iseg].m_Start; - wxPoint end = aZone->m_FillSegmList[iseg].m_End; - m_plotter->ThickSegment( start, end, - aZone->m_ZoneMinThickness, - GetMode() ); - } - } - - // Plot the current filled area outline - if( aZone->m_ZoneMinThickness > 0 ) - m_plotter->PlotPoly( cornerList, NO_FILL, aZone->m_ZoneMinThickness ); - } - else - { - if( aZone->m_ZoneMinThickness > 0 ) - { - for( unsigned jj = 1; jjThickSegment( cornerList[jj -1], cornerList[jj], - ( GetMode() == LINE ) ? -1 : aZone->m_ZoneMinThickness, - GetMode() ); - } - - m_plotter->SetCurrentLineWidth( -1 ); - } - - cornerList.clear(); - } - } -} - - -/* Plot items type DRAWSEGMENT on layers allowed by aLayerMask - */ -void BRDITEMS_PLOTTER::PlotDrawSegment( DRAWSEGMENT* aSeg ) -{ - int thickness; - int radius = 0, StAngle = 0, EndAngle = 0; - - if( (GetLayerMask( aSeg->GetLayer() ) & m_layerMask) == 0 ) - return; - - if( GetMode() == LINE ) - thickness = GetLineWidth(); - else - thickness = aSeg->GetWidth(); - - m_plotter->SetColor( getColor( aSeg->GetLayer() ) ); - - wxPoint start( aSeg->GetStart() ); - wxPoint end( aSeg->GetEnd() ); - - m_plotter->SetCurrentLineWidth( thickness ); - - switch( aSeg->GetShape() ) - { - case S_CIRCLE: - radius = (int) hypot( (double) ( end.x - start.x ), - (double) ( end.y - start.y ) ); - m_plotter->ThickCircle( start, radius * 2, thickness, GetMode() ); - break; - - case S_ARC: - radius = (int) hypot( (double) ( end.x - start.x ), - (double) ( end.y - start.y ) ); - StAngle = ArcTangente( end.y - start.y, end.x - start.x ); - EndAngle = StAngle + aSeg->GetAngle(); - m_plotter->ThickArc( start, -EndAngle, -StAngle, radius, thickness, GetMode() ); - break; - - case S_CURVE: - { - const std::vector& bezierPoints = aSeg->GetBezierPoints(); - - for( unsigned i = 1; i < bezierPoints.size(); i++ ) - m_plotter->ThickSegment( bezierPoints[i - 1], - bezierPoints[i], - thickness, GetMode() ); - } - break; - - default: - m_plotter->ThickSegment( start, end, thickness, GetMode() ); - } -} - - void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, int aLayer, const PCB_PLOT_PARAMS& aPlotOpt ) { @@ -1002,102 +477,21 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, itemplotter.PlotDrillMarks(); } -/** Helper function to plot a single drill mark. It compensate and clamp - * the drill mark size depending on the current plot options - */ -void BRDITEMS_PLOTTER::plotOneDrillMark( PAD_SHAPE_T aDrillShape, - const wxPoint &aDrillPos, wxSize aDrillSize, - const wxSize &aPadSize, - double aOrientation, int aSmallDrill ) -{ - // Small drill marks have no significance when applied to slots - if( aSmallDrill && aDrillShape == PAD_ROUND ) - aDrillSize.x = std::min( aSmallDrill, aDrillSize.x ); - - // Round holes only have x diameter, slots have both - aDrillSize.x -= getFineWidthAdj(); - aDrillSize.x = Clamp( 1, aDrillSize.x, aPadSize.x - 1 ); - if( aDrillShape == PAD_OVAL ) - { - aDrillSize.y -= getFineWidthAdj(); - aDrillSize.y = Clamp( 1, aDrillSize.y, aPadSize.y - 1 ); - m_plotter->FlashPadOval( aDrillPos, aDrillSize, aOrientation, GetMode() ); - } - else - m_plotter->FlashPadCircle( aDrillPos, aDrillSize.x, GetMode() ); -} - -/* Function PlotDrillMarks - * Draw a drill mark for pads and vias. - * Must be called after all drawings, because it - * redraw the drill mark on a pad or via, as a negative (i.e. white) shape in - * FILLED plot mode (for PS and PDF outputs) - */ -void BRDITEMS_PLOTTER::PlotDrillMarks() -{ - /* If small drills marks were requested prepare a clamp value to pass - to the helper function */ - int small_drill = (GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE) ? - SMALL_DRILL : 0; - - /* In the filled trace mode drill marks are drawn white-on-black to scrape - the underlying pad. This works only for drivers supporting color change, - obviously... it means that: - - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad) - - In HPGL you can't see them - - In gerbers you can't see them, too. This is arguably the right thing to - do since having drill marks and high speed drill stations is a sure - recipe for broken tools and angry manufacturers. If you *really* want them - you could start a layer with negative polarity to scrape the film. - - In DXF they go into the 'WHITE' layer. This could be useful. - */ - if( GetMode() == FILLED ) - m_plotter->SetColor( WHITE ); - - for( TRACK *pts = m_board->m_Track; pts != NULL; pts = pts->Next() ) - { - if( pts->Type() != PCB_VIA_T ) - continue; - - plotOneDrillMark(PAD_CIRCLE, - pts->m_Start, wxSize( pts->GetDrillValue(), 0 ), - wxSize( pts->m_Width, 0 ), 0, small_drill ); - } - - for( MODULE *Module = m_board->m_Modules; Module != NULL; Module = Module->Next() ) - { - for( D_PAD *pad = Module->m_Pads; pad != NULL; pad = pad->Next() ) - { - if( pad->GetDrillSize().x == 0 ) - continue; - - plotOneDrillMark( pad->GetDrillShape(), - pad->GetPosition(), pad->GetDrillSize(), - pad->GetSize(), pad->GetOrientation(), - small_drill ); - } - } - - if( GetMode() == FILLED ) - m_plotter->SetColor( GetColor() ); -} /** Set up most plot options for plotting a board (especially the viewport) * Important thing: * page size is the 'drawing' page size, * paper size is the physical page size */ -static void PlotSetupPlotter( PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts, - const PAGE_INFO &aPageInfo, - const EDA_RECT &aBbbox, - const wxPoint &aOrigin, - const wxString &aFilename ) +static void initializePlotter( PLOTTER *aPlotter, BOARD * aBoard, + PCB_PLOT_PARAMS *aPlotOpts ) { PAGE_INFO pageA4( wxT( "A4" ) ); + const PAGE_INFO& pageInfo = aBoard->GetPageSettings(); const PAGE_INFO* sheet_info; double paperscale; // Page-to-paper ratio wxSize paperSizeIU; - wxSize pageSizeIU( aPageInfo.GetSizeIU() ); + wxSize pageSizeIU( pageInfo.GetSizeIU() ); bool autocenter = false; /* Special options: to fit the sheet to an A4 sheet replace @@ -1116,7 +510,7 @@ static void PlotSetupPlotter( PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts, } else { - sheet_info = &aPageInfo; + sheet_info = &pageInfo; paperSizeIU = pageSizeIU; paperscale = 1; @@ -1124,10 +518,11 @@ static void PlotSetupPlotter( PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts, autocenter = (aPlotOpts->GetScale() != 1.0); } - wxPoint boardCenter = aBbbox.Centre(); + EDA_RECT bbox = aBoard->ComputeBoundingBox(); + wxPoint boardCenter = bbox.Centre(); + wxSize boardSize = bbox.GetSize(); double compound_scale; - wxSize boardSize = aBbbox.GetSize(); /* Fit to 80% of the page if asked; it could be that the board is empty, * in this case regress to 1:1 scale */ @@ -1155,7 +550,7 @@ static void PlotSetupPlotter( PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts, else { if( aPlotOpts->GetUseAuxOrigin() ) - offset = aOrigin; + offset = aBoard->GetOriginAxisPosition(); } /* Configure the plotter object with all the stuff computed and @@ -1167,7 +562,6 @@ static void PlotSetupPlotter( PLOTTER *aPlotter, PCB_PLOT_PARAMS *aPlotOpts, aPlotter->SetDefaultLineWidth( aPlotOpts->GetLineWidth() ); aPlotter->SetCreator( wxT( "PCBNEW" ) ); aPlotter->SetColorMode( false ); // default is plot in Black and White. - aPlotter->SetFilename( aFilename ); aPlotter->SetTextMode( aPlotOpts->GetTextMode() ); } @@ -1221,7 +615,6 @@ PLOTTER *StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, const wxString& aFullFileName, const wxString& aSheetDesc ) { - const PAGE_INFO& pageInfo = aBoard->GetPageSettings(); FILE* output_file = wxFopen( aFullFileName, wxT( "wt" ) ); if( output_file == NULL ) @@ -1272,21 +665,13 @@ PLOTTER *StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, if( the_plotter ) { - EDA_RECT bbbox = aBoard->ComputeBoundingBox(); - wxPoint auxOrigin( aBoard->GetOriginAxisPosition() ); + the_plotter->SetFilename( aFullFileName ); + // Compute the viewport and set the other options - PlotSetupPlotter( the_plotter, aPlotOpts, pageInfo, bbbox, auxOrigin, - aFullFileName ); + initializePlotter( the_plotter, aBoard, aPlotOpts ); if( the_plotter->StartPlot( output_file ) ) { - /* When plotting a negative board: draw a black rectangle - * (background for plot board in white) and switch the current - * color to WHITE; note the color inversion is actually done - * in the driver (if supported) */ - if( aPlotOpts->GetNegative() ) - FillNegativeKnockout( the_plotter, bbbox ); - // Plot the frame reference if requested if( aPlotOpts->GetPlotFrameRef() ) PlotWorkSheet( the_plotter, aBoard->GetTitleBlock(), @@ -1294,6 +679,16 @@ PLOTTER *StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, 1, 1, // Only one page aSheetDesc, aBoard->GetFileName() ); + /* When plotting a negative board: draw a black rectangle + * (background for plot board in white) and switch the current + * color to WHITE; note the color inversion is actually done + * in the driver (if supported) */ + if( aPlotOpts->GetNegative() ) + { + EDA_RECT bbox = aBoard->ComputeBoundingBox(); + FillNegativeKnockout( the_plotter, bbox ); + } + return the_plotter; } } diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp new file mode 100644 index 0000000000..6b8c413882 --- /dev/null +++ b/pcbnew/plot_brditems_plotter.cpp @@ -0,0 +1,685 @@ +/** + * @file plot_brditems_plotter.cpp + * @brief basic plot functions to plot board items, or a group of board items. + */ + + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * 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 write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* class BRDITEMS_PLOTTER is a helper class to plot board items + * and a group of board items + */ + + +/* Function getColor + * return the layer colorfrom the layer id + * White color is special: cannot be seen on a white paper + * and in B&W mode, is plotted as white but other colors are plotted in BLACK + * so the returned color is LIGHTGRAY when the layer color is WHITE + */ +EDA_COLOR_T BRDITEMS_PLOTTER::getColor( int aLayer ) +{ + EDA_COLOR_T color = m_board->GetLayerColor( aLayer ); + if (color == WHITE) + color = LIGHTGRAY; + return color; +} + +bool BRDITEMS_PLOTTER::PlotAllTextsModule( MODULE* aModule ) +{ + // see if we want to plot VALUE and REF fields + bool trace_val = GetPlotValue(); + bool trace_ref = GetPlotReference(); + + TEXTE_MODULE* textModule = aModule->m_Reference; + unsigned textLayer = textModule->GetLayer(); + + if( textLayer >= 32 ) + return false; + + if( ( ( 1 << textLayer ) & m_layerMask ) == 0 ) + trace_ref = false; + + if( !textModule->IsVisible() && !GetPlotInvisibleText() ) + trace_ref = false; + + textModule = aModule->m_Value; + textLayer = textModule->GetLayer(); + + if( textLayer > 32 ) + return false; + + if( ( (1 << textLayer) & m_layerMask ) == 0 ) + trace_val = false; + + if( !textModule->IsVisible() && !GetPlotInvisibleText() ) + trace_val = false; + + // Plot text fields, if allowed + if( trace_ref ) + { + if( GetReferenceColor() == UNSPECIFIED_COLOR ) + PlotTextModule( aModule->m_Reference, getColor( textLayer ) ); + else + PlotTextModule( aModule->m_Reference, GetReferenceColor() ); + } + + if( trace_val ) + { + if( GetValueColor() == UNSPECIFIED_COLOR ) + PlotTextModule( aModule->m_Value, getColor( textLayer ) ); + else + PlotTextModule( aModule->m_Value, GetValueColor() ); + } + + for( textModule = (TEXTE_MODULE*) aModule->m_Drawings.GetFirst(); + textModule != NULL; textModule = textModule->Next() ) + { + if( textModule->Type() != PCB_MODULE_TEXT_T ) + continue; + + if( !GetPlotOtherText() ) + continue; + + if( !textModule->IsVisible() && !GetPlotInvisibleText() ) + continue; + + textLayer = textModule->GetLayer(); + + if( textLayer >= 32 ) + return false; + + if( !( ( 1 << textLayer ) & m_layerMask ) ) + continue; + + PlotTextModule( textModule, getColor( textLayer ) ); + } + + return true; +} + + +// plot items like text and graphics, but not tracks and module +void BRDITEMS_PLOTTER::PlotBoardGraphicItems() +{ + for( BOARD_ITEM* item = m_board->m_Drawings; item; item = item->Next() ) + { + switch( item->Type() ) + { + case PCB_LINE_T: + PlotDrawSegment( (DRAWSEGMENT*) item); + break; + + case PCB_TEXT_T: + PlotTextePcb( (TEXTE_PCB*) item ); + break; + + case PCB_DIMENSION_T: + PlotDimension( (DIMENSION*) item ); + break; + + case PCB_TARGET_T: + PlotPcbTarget( (PCB_TARGET*) item ); + break; + + case PCB_MARKER_T: + default: + break; + } + } +} + +void BRDITEMS_PLOTTER::PlotTextModule( TEXTE_MODULE* pt_texte, + EDA_COLOR_T aColor ) +{ + wxSize size; + wxPoint pos; + int orient, thickness; + + if( aColor == WHITE ) + aColor = LIGHTGRAY; + m_plotter->SetColor( aColor ); + + // calculate some text parameters : + size = pt_texte->m_Size; + pos = pt_texte->m_Pos; + + orient = pt_texte->GetDrawRotation(); + + thickness = pt_texte->m_Thickness; + + if( GetMode() == LINE ) + thickness = -1; + + if( pt_texte->m_Mirror ) + NEGATE( size.x ); // Text is mirrored + + // Non bold texts thickness is clamped at 1/6 char size by the low level draw function. + // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size + // (like bold text) and we manage the thickness. + // So we set bold flag to true + bool allow_bold = pt_texte->m_Bold || thickness; + + m_plotter->Text( pos, aColor, + pt_texte->m_Text, + orient, size, + pt_texte->m_HJustify, pt_texte->m_VJustify, + thickness, pt_texte->m_Italic, allow_bold ); +} + + +void BRDITEMS_PLOTTER::PlotDimension( DIMENSION* aDim ) +{ + if( (GetLayerMask( aDim->GetLayer() ) & m_layerMask) == 0 ) + return; + + DRAWSEGMENT draw; + + draw.SetWidth( (GetMode() == LINE) ? -1 : aDim->GetWidth() ); + draw.SetLayer( aDim->GetLayer() ); + + EDA_COLOR_T color = aDim->GetBoard()->GetLayerColor( aDim->GetLayer() ); + // Set plot color (change WHITE to LIGHTGRAY because + // the white items are not seen on a white paper or screen + m_plotter->SetColor( color != WHITE ? color : LIGHTGRAY); + + PlotTextePcb( &aDim->m_Text ); + + draw.SetStart( wxPoint( aDim->m_crossBarOx, aDim->m_crossBarOy )); + draw.SetEnd( wxPoint( aDim->m_crossBarFx, aDim->m_crossBarFy )); + PlotDrawSegment( &draw ); + + draw.SetStart( wxPoint( aDim->m_featureLineGOx, aDim->m_featureLineGOy )); + draw.SetEnd( wxPoint( aDim->m_featureLineGFx, aDim->m_featureLineGFy )); + PlotDrawSegment( &draw ); + + draw.SetStart( wxPoint( aDim->m_featureLineDOx, aDim->m_featureLineDOy )); + draw.SetEnd( wxPoint( aDim->m_featureLineDFx, aDim->m_featureLineDFy )); + PlotDrawSegment( &draw ); + + draw.SetStart( wxPoint( aDim->m_arrowD1Ox, aDim->m_arrowD1Oy )); + draw.SetEnd( wxPoint( aDim->m_arrowD1Fx, aDim->m_arrowD1Fy )); + PlotDrawSegment( &draw ); + + draw.SetStart( wxPoint( aDim->m_arrowD2Ox, aDim->m_arrowD2Oy )); + draw.SetEnd( wxPoint( aDim->m_arrowD2Fx, aDim->m_arrowD2Fy )); + PlotDrawSegment( &draw ); + + draw.SetStart( wxPoint( aDim->m_arrowG1Ox, aDim->m_arrowG1Oy )); + draw.SetEnd( wxPoint( aDim->m_arrowG1Fx, aDim->m_arrowG1Fy )); + PlotDrawSegment( &draw ); + + draw.SetStart( wxPoint( aDim->m_arrowG2Ox, aDim->m_arrowG2Oy )); + draw.SetEnd( wxPoint( aDim->m_arrowG2Fx, aDim->m_arrowG2Fy )); + PlotDrawSegment( &draw ); +} + + +void BRDITEMS_PLOTTER::PlotPcbTarget( PCB_TARGET* aMire ) +{ + int dx1, dx2, dy1, dy2, radius; + + if( (GetLayerMask( aMire->GetLayer() ) & m_layerMask) == 0 ) + return; + + m_plotter->SetColor( getColor( aMire->GetLayer() ) ); + + DRAWSEGMENT draw; + + draw.SetShape( S_CIRCLE ); + draw.SetWidth( ( GetMode() == LINE ) ? -1 : aMire->GetWidth() ); + draw.SetLayer( aMire->GetLayer() ); + draw.SetStart( aMire->GetPosition() ); + radius = aMire->GetSize() / 3; + if( aMire->GetShape() ) // shape X + radius = aMire->GetSize() / 2; + + // Draw the circle + draw.SetEnd( wxPoint( draw.GetStart().x + radius, draw.GetStart().y )); + + PlotDrawSegment( &draw ); + + draw.SetShape( S_SEGMENT ); + + radius = aMire->GetSize() / 2; + dx1 = radius; + dy1 = 0; + dx2 = 0; + dy2 = radius; + + if( aMire->GetShape() ) // Shape X + { + dx1 = dy1 = radius; + dx2 = dx1; + dy2 = -dy1; + } + + wxPoint mirePos( aMire->GetPosition() ); + + // Draw the X or + shape: + draw.SetStart( wxPoint( mirePos.x - dx1, mirePos.y - dy1 )); + draw.SetEnd( wxPoint( mirePos.x + dx1, mirePos.y + dy1 )); + PlotDrawSegment( &draw ); + + draw.SetStart( wxPoint( mirePos.x - dx2, mirePos.y - dy2 )); + draw.SetEnd( wxPoint( mirePos.x + dx2, mirePos.y + dy2 )); + PlotDrawSegment( &draw ); +} + + +// Plot footprints graphic items (outlines) +void BRDITEMS_PLOTTER::Plot_Edges_Modules() +{ + for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) + { + for( EDGE_MODULE* edge = (EDGE_MODULE*) module->m_Drawings.GetFirst(); + edge; edge = edge->Next() ) + { + if( edge->Type() != PCB_MODULE_EDGE_T ) + continue; + + if( ( GetLayerMask( edge->GetLayer() ) & m_layerMask ) == 0 ) + continue; + + Plot_1_EdgeModule( edge ); + } + } +} + + +//* Plot a graphic item (outline) relative to a footprint +void BRDITEMS_PLOTTER::Plot_1_EdgeModule( EDGE_MODULE* aEdge ) +{ + int type_trace; // Type of item to plot. + int thickness; // Segment thickness. + int radius; // Circle radius. + + if( aEdge->Type() != PCB_MODULE_EDGE_T ) + return; + + m_plotter->SetColor( getColor( aEdge->GetLayer() ) ); + + type_trace = aEdge->GetShape(); + thickness = aEdge->GetWidth(); + + wxPoint pos( aEdge->GetStart() ); + wxPoint end( aEdge->GetEnd() ); + + switch( type_trace ) + { + case S_SEGMENT: + m_plotter->ThickSegment( pos, end, thickness, GetMode() ); + break; + + case S_CIRCLE: + radius = (int) hypot( (double) ( end.x - pos.x ), + (double) ( end.y - pos.y ) ); + m_plotter->ThickCircle( pos, radius * 2, thickness, GetMode() ); + break; + + case S_ARC: + { + radius = (int) hypot( (double) ( end.x - pos.x ), + (double) ( end.y - pos.y ) ); + + double startAngle = ArcTangente( end.y - pos.y, end.x - pos.x ); + + double endAngle = startAngle + aEdge->GetAngle(); + + if ( ( GetFormat() == PLOT_FORMAT_DXF ) && + ( m_layerMask & ( SILKSCREEN_LAYER_BACK | DRAW_LAYER | COMMENT_LAYER ) ) ) + m_plotter->ThickArc( pos, -startAngle, -endAngle, radius, + thickness, GetMode() ); + else + m_plotter->ThickArc( pos, -endAngle, -startAngle, radius, + thickness, GetMode() ); + } + break; + + case S_POLYGON: + { + const std::vector& polyPoints = aEdge->GetPolyPoints(); + + if( polyPoints.size() <= 1 ) // Malformed polygon + break; + + // We must compute true coordinates from m_PolyList + // which are relative to module position, orientation 0 + MODULE* module = aEdge->GetParentModule(); + + std::vector< wxPoint > cornerList; + + cornerList.reserve( polyPoints.size() ); + + for( unsigned ii = 0; ii < polyPoints.size(); ii++ ) + { + wxPoint corner = polyPoints[ii]; + + if( module ) + { + RotatePoint( &corner, module->GetOrientation() ); + corner += module->GetPosition(); + } + + cornerList.push_back( corner ); + } + + m_plotter->PlotPoly( cornerList, FILLED_SHAPE, thickness ); + } + break; + } +} + + +// Plot a PCB Text, i;e. a text found on a copper or technical layer +void BRDITEMS_PLOTTER::PlotTextePcb( TEXTE_PCB* pt_texte ) +{ + int orient, thickness; + wxPoint pos; + wxSize size; + + if( pt_texte->m_Text.IsEmpty() ) + return; + + if( ( GetLayerMask( pt_texte->GetLayer() ) & m_layerMask ) == 0 ) + return; + + m_plotter->SetColor( getColor( pt_texte->GetLayer() ) ); + + size = pt_texte->m_Size; + pos = pt_texte->m_Pos; + orient = pt_texte->m_Orient; + thickness = ( GetMode() == LINE ) ? -1 : pt_texte->m_Thickness; + + if( pt_texte->m_Mirror ) + size.x = -size.x; + + // Non bold texts thickness is clamped at 1/6 char size by the low level draw function. + // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size + // (like bold text) and we manage the thickness. + // So we set bold flag to true + bool allow_bold = pt_texte->m_Bold || thickness; + + if( pt_texte->m_MultilineAllowed ) + { + wxArrayString* list = wxStringSplit( pt_texte->m_Text, '\n' ); + wxPoint offset; + + offset.y = pt_texte->GetInterline(); + + RotatePoint( &offset, orient ); + + for( unsigned i = 0; i < list->Count(); i++ ) + { + wxString txt = list->Item( i ); + m_plotter->Text( pos, UNSPECIFIED_COLOR, txt, orient, size, + pt_texte->m_HJustify, pt_texte->m_VJustify, + thickness, pt_texte->m_Italic, allow_bold ); + pos += offset; + } + + delete list; + } + else + { + m_plotter->Text( pos, UNSPECIFIED_COLOR, pt_texte->m_Text, orient, size, + pt_texte->m_HJustify, pt_texte->m_VJustify, + thickness, pt_texte->m_Italic, allow_bold ); + } +} + + +/* Plot areas (given by .m_FilledPolysList member) in a zone + */ +void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) +{ + std::vector polysList = aZone->GetFilledPolysList(); + unsigned imax = polysList.size(); + + if( imax == 0 ) // Nothing to draw + return; + + // We need a buffer to store corners coordinates: + static std::vector< wxPoint > cornerList; + cornerList.clear(); + + m_plotter->SetColor( getColor( aZone->GetLayer() ) ); + + /* Plot all filled areas: filled areas have a filled area and a thick + * outline we must plot the filled area itself ( as a filled polygon + * OR a set of segments ) and plot the thick outline itself + * + * in non filled mode the outline is plotted, but not the filling items + */ + for( unsigned ic = 0; ic < imax; ic++ ) + { + CPolyPt* corner = &polysList[ic]; + cornerList.push_back( wxPoint( corner->x, corner->y) ); + + if( corner->end_contour ) // Plot the current filled area outline + { + // First, close the outline + if( cornerList[0] != cornerList[cornerList.size() - 1] ) + { + cornerList.push_back( cornerList[0] ); + } + + // Plot the current filled area and its outline + if( GetMode() == FILLED ) + { + // Plot the current filled area polygon + if( aZone->m_FillMode == 0 ) // We are using solid polygons + { // (if != 0: using segments ) + m_plotter->PlotPoly( cornerList, FILLED_SHAPE ); + } + else // We are using areas filled by + { // segments: plot them ) + for( unsigned iseg = 0; iseg < aZone->m_FillSegmList.size(); iseg++ ) + { + wxPoint start = aZone->m_FillSegmList[iseg].m_Start; + wxPoint end = aZone->m_FillSegmList[iseg].m_End; + m_plotter->ThickSegment( start, end, + aZone->m_ZoneMinThickness, + GetMode() ); + } + } + + // Plot the current filled area outline + if( aZone->m_ZoneMinThickness > 0 ) + m_plotter->PlotPoly( cornerList, NO_FILL, aZone->m_ZoneMinThickness ); + } + else + { + if( aZone->m_ZoneMinThickness > 0 ) + { + for( unsigned jj = 1; jjThickSegment( cornerList[jj -1], cornerList[jj], + ( GetMode() == LINE ) ? -1 : aZone->m_ZoneMinThickness, + GetMode() ); + } + + m_plotter->SetCurrentLineWidth( -1 ); + } + + cornerList.clear(); + } + } +} + + +/* Plot items type DRAWSEGMENT on layers allowed by aLayerMask + */ +void BRDITEMS_PLOTTER::PlotDrawSegment( DRAWSEGMENT* aSeg ) +{ + int thickness; + int radius = 0, StAngle = 0, EndAngle = 0; + + if( (GetLayerMask( aSeg->GetLayer() ) & m_layerMask) == 0 ) + return; + + if( GetMode() == LINE ) + thickness = GetLineWidth(); + else + thickness = aSeg->GetWidth(); + + m_plotter->SetColor( getColor( aSeg->GetLayer() ) ); + + wxPoint start( aSeg->GetStart() ); + wxPoint end( aSeg->GetEnd() ); + + m_plotter->SetCurrentLineWidth( thickness ); + + switch( aSeg->GetShape() ) + { + case S_CIRCLE: + radius = (int) hypot( (double) ( end.x - start.x ), + (double) ( end.y - start.y ) ); + m_plotter->ThickCircle( start, radius * 2, thickness, GetMode() ); + break; + + case S_ARC: + radius = (int) hypot( (double) ( end.x - start.x ), + (double) ( end.y - start.y ) ); + StAngle = ArcTangente( end.y - start.y, end.x - start.x ); + EndAngle = StAngle + aSeg->GetAngle(); + m_plotter->ThickArc( start, -EndAngle, -StAngle, radius, thickness, GetMode() ); + break; + + case S_CURVE: + { + const std::vector& bezierPoints = aSeg->GetBezierPoints(); + + for( unsigned i = 1; i < bezierPoints.size(); i++ ) + m_plotter->ThickSegment( bezierPoints[i - 1], + bezierPoints[i], + thickness, GetMode() ); + } + break; + + default: + m_plotter->ThickSegment( start, end, thickness, GetMode() ); + } +} + +/** Helper function to plot a single drill mark. It compensate and clamp + * the drill mark size depending on the current plot options + */ +void BRDITEMS_PLOTTER::plotOneDrillMark( PAD_SHAPE_T aDrillShape, + const wxPoint &aDrillPos, wxSize aDrillSize, + const wxSize &aPadSize, + double aOrientation, int aSmallDrill ) +{ + // Small drill marks have no significance when applied to slots + if( aSmallDrill && aDrillShape == PAD_ROUND ) + aDrillSize.x = std::min( aSmallDrill, aDrillSize.x ); + + // Round holes only have x diameter, slots have both + aDrillSize.x -= getFineWidthAdj(); + aDrillSize.x = Clamp( 1, aDrillSize.x, aPadSize.x - 1 ); + if( aDrillShape == PAD_OVAL ) + { + aDrillSize.y -= getFineWidthAdj(); + aDrillSize.y = Clamp( 1, aDrillSize.y, aPadSize.y - 1 ); + m_plotter->FlashPadOval( aDrillPos, aDrillSize, aOrientation, GetMode() ); + } + else + m_plotter->FlashPadCircle( aDrillPos, aDrillSize.x, GetMode() ); +} + +/* Function PlotDrillMarks + * Draw a drill mark for pads and vias. + * Must be called after all drawings, because it + * redraw the drill mark on a pad or via, as a negative (i.e. white) shape in + * FILLED plot mode (for PS and PDF outputs) + */ +void BRDITEMS_PLOTTER::PlotDrillMarks() +{ + /* If small drills marks were requested prepare a clamp value to pass + to the helper function */ + int small_drill = (GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE) ? + SMALL_DRILL : 0; + + /* In the filled trace mode drill marks are drawn white-on-black to scrape + the underlying pad. This works only for drivers supporting color change, + obviously... it means that: + - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad) + - In HPGL you can't see them + - In gerbers you can't see them, too. This is arguably the right thing to + do since having drill marks and high speed drill stations is a sure + recipe for broken tools and angry manufacturers. If you *really* want them + you could start a layer with negative polarity to scrape the film. + - In DXF they go into the 'WHITE' layer. This could be useful. + */ + if( GetMode() == FILLED ) + m_plotter->SetColor( WHITE ); + + for( TRACK *pts = m_board->m_Track; pts != NULL; pts = pts->Next() ) + { + if( pts->Type() != PCB_VIA_T ) + continue; + + plotOneDrillMark(PAD_CIRCLE, + pts->m_Start, wxSize( pts->GetDrillValue(), 0 ), + wxSize( pts->m_Width, 0 ), 0, small_drill ); + } + + for( MODULE *Module = m_board->m_Modules; Module != NULL; Module = Module->Next() ) + { + for( D_PAD *pad = Module->m_Pads; pad != NULL; pad = pad->Next() ) + { + if( pad->GetDrillSize().x == 0 ) + continue; + + plotOneDrillMark( pad->GetDrillShape(), + pad->GetPosition(), pad->GetDrillSize(), + pad->GetSize(), pad->GetOrientation(), + small_drill ); + } + } + + if( GetMode() == FILLED ) + m_plotter->SetColor( GetColor() ); +} diff --git a/pcbnew/scripting/pcbnew_footprint_wizards.cpp b/pcbnew/scripting/pcbnew_footprint_wizards.cpp index 3c59c2502a..db93029458 100644 --- a/pcbnew/scripting/pcbnew_footprint_wizards.cpp +++ b/pcbnew/scripting/pcbnew_footprint_wizards.cpp @@ -11,7 +11,7 @@ PYTHON_FOOTPRINT_WIZARD::PYTHON_FOOTPRINT_WIZARD(PyObject *aWizard) { this->m_PyWizard= aWizard; - Py_XINCREF( aWizard ); + Py_XINCREF( aWizard ); } PYTHON_FOOTPRINT_WIZARD::~PYTHON_FOOTPRINT_WIZARD() @@ -22,18 +22,18 @@ PYTHON_FOOTPRINT_WIZARD::~PYTHON_FOOTPRINT_WIZARD() PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aArglist) { PyObject *pFunc; - + /* pFunc is a new reference to the desired method */ pFunc = PyObject_GetAttrString( this->m_PyWizard, aMethod ); - - if ( pFunc && PyCallable_Check( pFunc ) ) + + if ( pFunc && PyCallable_Check( pFunc ) ) { PyObject *result; PY_BLOCK_THREADS( blocked ); result = PyObject_CallObject( pFunc, aArglist ); - + if ( PyErr_Occurred() ) { PyObject *t, *v, *b; @@ -44,29 +44,29 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr } PY_UNBLOCK_THREADS( blocked ); - + if ( result ) { Py_XDECREF( pFunc ); return result; } - + } else { printf( "method not found, or not callable: %s\n", aMethod ); } - - if ( pFunc ) + + if ( pFunc ) Py_XDECREF( pFunc ); - + return NULL; } wxString PYTHON_FOOTPRINT_WIZARD::CallRetStrMethod( const char* aMethod, PyObject *aArglist ) { wxString ret; - + ret.Clear(); PyObject *result = CallMethod( aMethod, aArglist ); if ( result ) @@ -74,7 +74,7 @@ wxString PYTHON_FOOTPRINT_WIZARD::CallRetStrMethod( const char* aMethod, PyObjec PY_BLOCK_THREADS( blocked ); const char *str_res = PyString_AsString( result ); ret = wxString::FromUTF8( str_res ); - Py_DECREF( result ); + Py_DECREF( result ); PY_UNBLOCK_THREADS( blocked ); } @@ -87,9 +87,9 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod PyObject *result, *element; wxArrayString ret; wxString str_item; - + result = CallMethod( aMethod, aArglist ); - + if ( result ) { if ( !PyList_Check(result) ) @@ -101,9 +101,9 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod } PY_BLOCK_THREADS( blocked ); - + int list_size = PyList_Size( result ); - + for ( int n=0; nGetName().mb_str() // ); - + // this get the wizard registered in the common // FOOTPRINT_WIZARDS class - - fw->register_wizard(); - -#if 0 + + fw->register_wizard(); + +#if 0 /* just to test if it works correctly */ int pages = fw->GetNumParameterPages(); printf(" %d pages\n",pages); - + for (int n=0; n'%s'\n",n, (const char*)fw->GetParameterPageName(n).mb_str()); } -#endif - +#endif + }