void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width, EDA_DRAW_MODE_T tracemode, void* aData ) { GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData ); SetCurrentLineWidth( width, gbr_metadata ); if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); if( tracemode == FILLED ) Rect( p1, p2, NO_FILL, DO_NOT_SET_LINE_WIDTH ); else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); wxPoint offsetp1( p1.x - (width - currentPenWidth) / 2, p1.y - (width - currentPenWidth) / 2 ); wxPoint offsetp2( p2.x + (width - currentPenWidth) / 2, p2.y + (width - currentPenWidth) / 2 ); Rect( offsetp1, offsetp2, NO_FILL, -1 ); offsetp1.x += (width - currentPenWidth); offsetp1.y += (width - currentPenWidth); offsetp2.x -= (width - currentPenWidth); offsetp2.y -= (width - currentPenWidth); Rect( offsetp1, offsetp2, NO_FILL, DO_NOT_SET_LINE_WIDTH ); } }
/** * Function PLOTTER::Text * same as DrawGraphicText, but plot graphic text insteed of draw it * @param aPos = text position (according to aH_justify, aV_justify) * @param aColor (COLOR4D) = text color * @param aText = text to draw * @param aOrient = angle in 0.1 degree * @param aSize = text size (size.x or size.y can be < 0 for mirrored texts) * @param aH_justify = horizontal justification (Left, center, right) * @param aV_justify = vertical justification (bottom, center, top) * @param aWidth = line width (pen width) (default = 0) * if width < 0 : draw segments in sketch mode, width = abs(width) * Use a value min(aSize.x, aSize.y) / 5 for a bold text * @param aItalic = true to simulate an italic font * @param aBold = true to use a bold font Useful only with default width value (aWidth = 0) * @param aMultilineAllowed = true to plot text as multiline, otherwise single line */ void PLOTTER::Text( const wxPoint& aPos, const COLOR4D aColor, const wxString& aText, double aOrient, const wxSize& aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed, void* aData ) { int textPensize = aWidth; if( textPensize == 0 && aBold ) // Use default values if aWidth == 0 textPensize = GetPenSizeForBold( std::min( aSize.x, aSize.y ) ); if( textPensize >= 0 ) textPensize = Clamp_Text_PenSize( aWidth, aSize, aBold ); else textPensize = -Clamp_Text_PenSize( -aWidth, aSize, aBold ); SetCurrentLineWidth( textPensize, aData ); SetColor( aColor ); DrawGraphicText( NULL, NULL, aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, textPensize, aItalic, aBold, NULL, this ); if( aWidth != textPensize ) SetCurrentLineWidth( aWidth, aData ); }
void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, EDA_DRAW_MODE_T aTraceMode, void* aData ) { wxSize size( aSize ); if( aTraceMode == FILLED ) SetCurrentLineWidth( 0 ); else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); size.x -= GetCurrentLineWidth(); size.y -= GetCurrentLineWidth(); } std::vector< wxPoint > cornerList; for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt ) { SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt ); cornerList.clear(); for( int ii = 0; ii < poly.PointCount(); ++ii ) cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); // Close polygon cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, GetCurrentLineWidth() ); } }
void PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width, EDA_DRAW_MODE_T tracemode ) { if( tracemode == FILLED ) { SetCurrentLineWidth( width ); MoveTo( start ); FinishTo( end ); } else { SetCurrentLineWidth( -1 ); segmentAsOval( start, end, width, tracemode ); } }
void PSLIKE_PLOTTER::FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { static std::vector< wxPoint > cornerList; wxSize size( aSize ); cornerList.clear(); if( aTraceMode == FILLED ) SetCurrentLineWidth( 0 ); else SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); size.x -= GetCurrentLineWidth(); size.y -= GetCurrentLineWidth(); if( size.x < 1 ) size.x = 1; if( size.y < 1 ) size.y = 1; int dx = size.x / 2; int dy = size.y / 2; wxPoint corner; corner.x = aPadPos.x - dx; corner.y = aPadPos.y + dy; cornerList.push_back( corner ); corner.x = aPadPos.x - dx; corner.y = aPadPos.y - dy; cornerList.push_back( corner ); corner.x = aPadPos.x + dx; corner.y = aPadPos.y - dy; cornerList.push_back( corner ); corner.x = aPadPos.x + dx; corner.y = aPadPos.y + dy, cornerList.push_back( corner ); for( unsigned ii = 0; ii < cornerList.size(); ii++ ) { RotatePoint( &cornerList[ii], aPadPos, aPadOrient ); } cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, GetCurrentLineWidth() ); }
void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle, int aRadius, FILL_T aFill, int aWidth ) { SetCurrentLineWidth( aWidth ); wxPoint start, end; start.x = aCenter.x + KiROUND( cosdecideg( aRadius, aStAngle ) ); start.y = aCenter.y - KiROUND( sindecideg( aRadius, aStAngle ) ); MoveTo( start ); end.x = aCenter.x + KiROUND( cosdecideg( aRadius, aEndAngle ) ); end.y = aCenter.y - KiROUND( sindecideg( aRadius, aEndAngle ) ); DPOINT devEnd = userToDeviceCoordinates( end ); DPOINT devCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start ); fprintf( outputFile, "G75*\n" ); // Multiquadrant mode if( aStAngle < aEndAngle ) fprintf( outputFile, "G03" ); else fprintf( outputFile, "G02" ); fprintf( outputFile, "X%dY%dI%dJ%dD01*\n", KiROUND( devEnd.x ), KiROUND( devEnd.y ), KiROUND( devCenter.x ), KiROUND( devCenter.y ) ); fprintf( outputFile, "G01*\n" ); // Back to linear interp. }
void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_T aFill, int aWidth ) { if( aCornerList.size() <= 1 ) return; setFillMode( aFill ); SetCurrentLineWidth( aWidth ); switch( aFill ) { case NO_FILL: fprintf( outputFile, "<polyline fill=\"none;\"\n" ); break; case FILLED_WITH_BG_BODYCOLOR: case FILLED_SHAPE: fprintf( outputFile, "<polyline style=\"fill-rule:evenodd;\"\n" ); break; } DPOINT pos = userToDeviceCoordinates( aCornerList[0] ); fprintf( outputFile, "points=\"%d,%d\n", (int) pos.x, (int) pos.y ); for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) { pos = userToDeviceCoordinates( aCornerList[ii] ); fprintf( outputFile, "%d,%d\n", (int) pos.x, (int) pos.y ); } // Close/(fill) the path fprintf( outputFile, "\" /> \n" ); }
void PS_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, FILL_T fill, int width ) { wxASSERT( outputFile ); if( radius <= 0 ) return; if( StAngle > EndAngle ) EXCHG( StAngle, EndAngle ); SetCurrentLineWidth( width ); // Calculate start point. DPOINT centre_dev = userToDeviceCoordinates( centre ); double radius_dev = userToDeviceSize( radius ); if( m_plotMirror ) { if( m_mirrorIsHorizontal ) { StAngle = 1800.0 -StAngle; EndAngle = 1800.0 -EndAngle; EXCHG( StAngle, EndAngle ); } else { StAngle = -StAngle; EndAngle = -EndAngle; } } fprintf( outputFile, "%g %g %g %g %g arc%d\n", centre_dev.x, centre_dev.y, radius_dev, StAngle / 10.0, EndAngle / 10.0, fill ); }
void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, EDA_DRAW_MODE_T trace_mode, void* aData ) { wxSize size( diametre, diametre ); GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData ); if( trace_mode == SKETCH ) { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); Circle( pos, diametre - currentPenWidth, NO_FILL, DO_NOT_SET_LINE_WIDTH ); } else { DPOINT pos_dev = userToDeviceCoordinates( pos ); int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0; selectAperture( size, APERTURE::Circle, aperture_attrib ); if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); emitDcode( pos_dev, 3 ); } }
void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, FILL_T fill, int width ) { wxPoint start, end; const int delta = 50; // increment (in 0.1 degrees) to draw circles if( StAngle > EndAngle ) std::swap( StAngle, EndAngle ); SetCurrentLineWidth( width ); /* Please NOTE the different sign due to Y-axis flip */ start.x = centre.x + KiROUND( cosdecideg( radius, -StAngle ) ); start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) ); MoveTo( start ); for( int ii = StAngle + delta; ii < EndAngle; ii += delta ) { end.x = centre.x + KiROUND( cosdecideg( radius, -ii ) ); end.y = centre.y + KiROUND( sindecideg( radius, -ii ) ); LineTo( end ); } end.x = centre.x + KiROUND( cosdecideg( radius, -EndAngle ) ); end.y = centre.y + KiROUND( sindecideg( radius, -EndAngle ) ); FinishTo( end ); }
void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, double orient, EDA_DRAW_MODE_T trace_mode ) { wxASSERT( outputFile ); wxSize size( aSize ); // Plot as an aperture flash switch( int( orient ) ) { case 900: case 2700: // rotation of 90 degrees or 270 swaps sizes EXCHG( size.x, size.y ); // Pass through case 0: case 1800: if( trace_mode == SKETCH ) { SetCurrentLineWidth( -1 ); Rect( wxPoint( pos.x - (size.x - currentPenWidth) / 2, pos.y - (size.y - currentPenWidth) / 2 ), wxPoint( pos.x + (size.x - currentPenWidth) / 2, pos.y + (size.y - currentPenWidth) / 2 ), NO_FILL ); } else { DPOINT pos_dev = userToDeviceCoordinates( pos ); selectAperture( size, APERTURE::Rect ); emitDcode( pos_dev, 3 ); } break; default: // plot pad shape as polygon { // XXX to do: use an aperture macro to declare the rotated pad wxPoint coord[4]; // coord[0] is assumed the lower left // coord[1] is assumed the upper left // coord[2] is assumed the upper right // coord[3] is assumed the lower right /* Trace the outline. */ coord[0].x = -size.x/2; // lower left coord[0].y = size.y/2; coord[1].x = -size.x/2; // upper left coord[1].y = -size.y/2; coord[2].x = size.x/2; // upper right coord[2].y = -size.y/2; coord[3].x = size.x/2; // lower right coord[3].y = size.y/2; FlashPadTrapez( pos, coord, orient, trace_mode ); } break; } }
void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, EDA_DRAW_MODE_T modetrace ) { int current_line_width; wxASSERT( outputFile ); SetCurrentLineWidth( -1 ); current_line_width = GetCurrentLineWidth(); if( current_line_width > diametre ) current_line_width = diametre; if( modetrace == FILLED ) Circle( pos, diametre - currentPenWidth, FILLED_SHAPE, current_line_width ); else Circle( pos, diametre - currentPenWidth, NO_FILL, current_line_width ); SetCurrentLineWidth( -1 ); }
void PS_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_T fill, int width ) { wxASSERT( outputFile ); DPOINT pos_dev = userToDeviceCoordinates( pos ); double radius = userToDeviceSize( diametre / 2.0 ); SetCurrentLineWidth( width ); fprintf( outputFile, "%g %g %g cir%d\n", pos_dev.x, pos_dev.y, radius, fill ); }
void PS_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width ) { DPOINT p1_dev = userToDeviceCoordinates( p1 ); DPOINT p2_dev = userToDeviceCoordinates( p2 ); SetCurrentLineWidth( width ); fprintf( outputFile, "%g %g %g %g rect%d\n", p1_dev.x, p1_dev.y, p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y, fill ); }
void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { static std::vector< wxPoint > cornerList; cornerList.clear(); for( int ii = 0; ii < 4; ii++ ) cornerList.push_back( aCorners[ii] ); if( aTraceMode == FILLED ) { SetCurrentLineWidth( 0 ); } else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); int w = GetCurrentLineWidth(); // offset polygon by w // coord[0] is assumed the lower left // coord[1] is assumed the upper left // coord[2] is assumed the upper right // coord[3] is assumed the lower right /* Trace the outline. */ cornerList[0].x += w; cornerList[0].y -= w; cornerList[1].x += w; cornerList[1].y += w; cornerList[2].x -= w; cornerList[2].y += w; cornerList[3].x -= w; cornerList[3].y -= w; } for( int ii = 0; ii < 4; ii++ ) { RotatePoint( &cornerList[ii], aPadOrient ); cornerList[ii] += aPadPos; } cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, GetCurrentLineWidth() ); }
void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& aPadPos, int aDiameter, EDA_DRAW_MODE_T aTraceMode, void* aData ) { if( aTraceMode == FILLED ) Circle( aPadPos, aDiameter, FILLED_SHAPE, 0 ); else // Plot a ring: { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); int linewidth = GetCurrentLineWidth(); // avoid aDiameter <= 1 ) if( linewidth > aDiameter-2 ) linewidth = aDiameter-2; Circle( aPadPos, aDiameter - linewidth, NO_FILL, linewidth ); } SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); }
void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_T aFill, int aWidth ) { if( aCornerList.size() <= 1 ) return; SetCurrentLineWidth( aWidth ); MoveTo( aCornerList[0] ); if( aFill == FILLED_SHAPE ) { // Draw the filled area SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); fprintf( outputFile, "PM 0;\n" ); // Start polygon for( unsigned ii = 1; ii < aCornerList.size(); ++ii ) LineTo( aCornerList[ii] ); int ii = aCornerList.size() - 1; if( aCornerList[ii] != aCornerList[0] ) LineTo( aCornerList[0] ); fprintf( outputFile, hpgl_end_polygon_cmd ); // Close, fill polygon and draw outlines } else { // Plot only the polygon outline. for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) LineTo( aCornerList[ii] ); // Always close polygon if filled. if( aFill ) { int ii = aCornerList.size() - 1; if( aCornerList[ii] != aCornerList[0] ) LineTo( aCornerList[0] ); } } PenFinish(); }
void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, EDA_DRAW_MODE_T aTraceMode, void* aData ) { // A Pad custom is plotted as polygon. // A flashed circle @aPadPos is added (anchor pad) // However, because the anchor pad can be circle or rect, we use only // a circle not bigger than the rect. // the main purpose is to print a flashed DCode as pad anchor if( aTraceMode == FILLED ) FlashPadCircle( aPadPos, std::min( aSize.x, aSize.y ), aTraceMode, aData ); GBR_METADATA gbr_metadata; if( aData ) { gbr_metadata = *static_cast<GBR_METADATA*>( aData ); // If the pad is drawn on a copper layer, // set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR if( gbr_metadata.IsCopper() ) gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); wxString attrname( ".P" ); gbr_metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers } SHAPE_POLY_SET polyshape = *aPolygons; if( aTraceMode != FILLED ) { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); polyshape.Inflate( -GetCurrentLineWidth()/2, 16 ); } std::vector< wxPoint > cornerList; for( int cnt = 0; cnt < polyshape.OutlineCount(); ++cnt ) { SHAPE_LINE_CHAIN& poly = polyshape.Outline( cnt ); cornerList.clear(); for( int ii = 0; ii < poly.PointCount(); ++ii ) cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); // Close polygon cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL, aTraceMode == FILLED ? 0 : GetCurrentLineWidth(), &gbr_metadata ); } }
/** * Function start_plot * Write GERBER header to file * initialize global variable g_Plot_PlotOutputFile */ bool GERBER_PLOTTER::StartPlot() { wxASSERT( outputFile ); finalFile = outputFile; // the actual gerber file will be created later // Create a temporary filename to store gerber file // note tmpfile() does not work under Vista and W7 in user mode m_workFilename = filename + wxT(".tmp"); workFile = wxFopen( m_workFilename, wxT( "wt" )); outputFile = workFile; wxASSERT( outputFile ); if( outputFile == NULL ) return false; if( ! m_attribFunction.IsEmpty() ) { fprintf( outputFile, "%%TF.FileFunction,%s*%%\n", TO_UTF8( m_attribFunction ) ); } // Set coordinate format to 3.6 or 4.5 absolute, leading zero omitted // the number of digits for the integer part of coordintes is needed // in gerber format, but is not very important when omitting leading zeros // It is fixed here to 3 (inch) or 4 (mm), but is not actually used int leadingDigitCount = m_gerberUnitInch ? 3 : 4; fprintf( outputFile, "%%FSLAX%d%dY%d%d*%%\n", leadingDigitCount, m_gerberUnitFmt, leadingDigitCount, m_gerberUnitFmt ); fprintf( outputFile, "G04 Gerber Fmt %d.%d, Leading zero omitted, Abs format (unit %s)*\n", leadingDigitCount, m_gerberUnitFmt, m_gerberUnitInch ? "inch" : "mm" ); wxString Title = creator + wxT( " " ) + GetBuildVersion(); fprintf( outputFile, "G04 Created by KiCad (%s) date %s*\n", TO_UTF8( Title ), TO_UTF8( DateAndTime() ) ); /* Mass parameter: unit = INCHES/MM */ if( m_gerberUnitInch ) fputs( "%MOIN*%\n", outputFile ); else fputs( "%MOMM*%\n", outputFile ); /* Specify linear interpol (G01) */ fputs( "G01*\n", outputFile ); fputs( "G04 APERTURE LIST*\n", outputFile ); /* Select the default aperture */ SetCurrentLineWidth( -1 ); return true; }
void GERBER_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width, EDA_DRAW_MODE_T tracemode, void* aData ) { if( tracemode == FILLED ) { GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData ); SetCurrentLineWidth( width, gbr_metadata ); if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); MoveTo( start ); FinishTo( end ); } else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); segmentAsOval( start, end, width, tracemode ); } }
void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { GBR_METADATA gbr_metadata; if( aData ) { gbr_metadata = *static_cast<GBR_METADATA*>( aData ); // If the pad is drawn on a copper layer, // set attribute to GBR_APERTURE_ATTRIB_CONDUCTOR if( gbr_metadata.IsCopper() ) gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); wxString attrname( ".P" ); gbr_metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers } if( aTraceMode != FILLED ) SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); // Currently, a Pad RoundRect is plotted as polygon. // TODO: use Aperture macro and flash it SHAPE_POLY_SET outline; const int segmentToCircleCount = 64; TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius, segmentToCircleCount ); if( aTraceMode != FILLED ) outline.Inflate( -GetCurrentLineWidth()/2, 16 ); std::vector< wxPoint > cornerList; // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); cornerList.reserve( poly.PointCount() + 1 ); for( int ii = 0; ii < poly.PointCount(); ++ii ) cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); // Close polygon cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, aTraceMode == FILLED ? FILLED_SHAPE : NO_FILL, aTraceMode == FILLED ? 0 : GetCurrentLineWidth(), &gbr_metadata ); // Now, flash a pad anchor, if a netlist attribute is set // (remove me when a Aperture macro will be used) if( aData && aTraceMode == FILLED ) { int diameter = std::min( aSize.x, aSize.y ); FlashPadCircle( aPadPos, diameter, aTraceMode , aData ); } }
void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width, EDA_DRAW_MODE_T tracemode, void* aData ) { GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData ); SetCurrentLineWidth( width, gbr_metadata ); if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); if( tracemode == FILLED ) Circle( pos, diametre, NO_FILL, DO_NOT_SET_LINE_WIDTH ); else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); Circle( pos, diametre - (width - currentPenWidth), NO_FILL, DO_NOT_SET_LINE_WIDTH ); Circle( pos, diametre + (width - currentPenWidth), NO_FILL, DO_NOT_SET_LINE_WIDTH ); } }
/** * Rectangles in PDF. Supported by the native operator */ void PDF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill, int width ) { wxASSERT( workFile ); DPOINT p1_dev = userToDeviceCoordinates( p1 ); DPOINT p2_dev = userToDeviceCoordinates( p2 ); SetCurrentLineWidth( width ); fprintf( workFile, "%g %g %g %g re %c\n", p1_dev.x, p1_dev.y, p2_dev.x - p1_dev.x, p2_dev.y - p1_dev.y, fill == NO_FILL ? 'S' : 'B' ); }
void PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width, EDA_DRAW_MODE_T tracemode ) { if( tracemode == FILLED ) Circle( pos, diametre, NO_FILL, width ); else { SetCurrentLineWidth( -1 ); Circle( pos, diametre - width + currentPenWidth, NO_FILL, -1 ); Circle( pos, diametre + width - currentPenWidth, NO_FILL, -1 ); } }
void SVG_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_T fill, int width ) { DPOINT pos_dev = userToDeviceCoordinates( pos ); double radius = userToDeviceSize( diametre / 2.0 ); setFillMode( fill ); SetCurrentLineWidth( width ); fprintf( outputFile, "<circle cx=\"%g\" cy=\"%g\" r=\"%g\" /> \n", pos_dev.x, pos_dev.y, radius ); }
void GERBER_PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle, int radius, int width, EDA_DRAW_MODE_T tracemode, void* aData ) { GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData ); SetCurrentLineWidth( width, gbr_metadata ); if( gbr_metadata ) formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); if( tracemode == FILLED ) Arc( centre, StAngle, EndAngle, radius, NO_FILL, DO_NOT_SET_LINE_WIDTH ); else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); Arc( centre, StAngle, EndAngle, radius - ( width - currentPenWidth ) / 2, NO_FILL, DO_NOT_SET_LINE_WIDTH ); Arc( centre, StAngle, EndAngle, radius + ( width - currentPenWidth ) / 2, NO_FILL, DO_NOT_SET_LINE_WIDTH ); } }
void PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle, int radius, int width, EDA_DRAW_MODE_T tracemode ) { if( tracemode == FILLED ) Arc( centre, StAngle, EndAngle, radius, NO_FILL, width ); else { SetCurrentLineWidth( -1 ); Arc( centre, StAngle, EndAngle, radius - ( width - currentPenWidth ) / 2, NO_FILL, -1 ); Arc( centre, StAngle, EndAngle, radius + ( width - currentPenWidth ) / 2, NO_FILL, -1 ); } }
void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { wxSize size( aSize ); if( aTraceMode == FILLED ) SetCurrentLineWidth( 0 ); else { SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); size.x -= GetCurrentLineWidth(); size.y -= GetCurrentLineWidth(); aCornerRadius -= GetCurrentLineWidth()/2; } SHAPE_POLY_SET outline; const int segmentToCircleCount = 64; TransformRoundRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius, segmentToCircleCount ); std::vector< wxPoint > cornerList; cornerList.reserve( segmentToCircleCount + 5 ); // TransformRoundRectToPolygon creates only one convex polygon SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); for( int ii = 0; ii < poly.PointCount(); ++ii ) cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); // Close polygon cornerList.push_back( cornerList[0] ); PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, GetCurrentLineWidth() ); }
/** * The PDF engine can't directly plot arcs, it uses the base emulation. * So no filled arcs (not a great loss... ) */ void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, FILL_T fill, int width ) { wxASSERT( workFile ); if( radius <= 0 ) return; /* Arcs are not so easily approximated by beziers (in the general case), so we approximate them in the old way */ wxPoint start, end; const int delta = 50; // increment (in 0.1 degrees) to draw circles if( StAngle > EndAngle ) EXCHG( StAngle, EndAngle ); SetCurrentLineWidth( width ); // Usual trig arc plotting routine... start.x = centre.x + KiROUND( cosdecideg( radius, -StAngle ) ); start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) ); DPOINT pos_dev = userToDeviceCoordinates( start ); fprintf( workFile, "%g %g m ", pos_dev.x, pos_dev.y ); for( int ii = StAngle + delta; ii < EndAngle; ii += delta ) { end.x = centre.x + KiROUND( cosdecideg( radius, -ii ) ); end.y = centre.y + KiROUND( sindecideg( radius, -ii ) ); pos_dev = userToDeviceCoordinates( end ); fprintf( workFile, "%g %g l ", pos_dev.x, pos_dev.y ); } end.x = centre.x + KiROUND( cosdecideg( radius, -EndAngle ) ); end.y = centre.y + KiROUND( sindecideg( radius, -EndAngle ) ); pos_dev = userToDeviceCoordinates( end ); fprintf( workFile, "%g %g l ", pos_dev.x, pos_dev.y ); // The arc is drawn... if not filled we stroke it, otherwise we finish // closing the pie at the center if( fill == NO_FILL ) { fputs( "S\n", workFile ); } else { pos_dev = userToDeviceCoordinates( centre ); fprintf( workFile, "%g %g l b\n", pos_dev.x, pos_dev.y ); } }
void PLOTTER::sketchOval( const wxPoint& pos, const wxSize& aSize, double orient, int width ) { SetCurrentLineWidth( width ); width = currentPenWidth; int radius, deltaxy, cx, cy; wxSize size( aSize ); if( size.x > size.y ) { std::swap( size.x, size.y ); orient = AddAngles( orient, 900 ); } deltaxy = size.y - size.x; /* distance between centers of the oval */ radius = ( size.x - width ) / 2; cx = -radius; cy = -deltaxy / 2; RotatePoint( &cx, &cy, orient ); MoveTo( wxPoint( cx + pos.x, cy + pos.y ) ); cx = -radius; cy = deltaxy / 2; RotatePoint( &cx, &cy, orient ); FinishTo( wxPoint( cx + pos.x, cy + pos.y ) ); cx = radius; cy = -deltaxy / 2; RotatePoint( &cx, &cy, orient ); MoveTo( wxPoint( cx + pos.x, cy + pos.y ) ); cx = radius; cy = deltaxy / 2; RotatePoint( &cx, &cy, orient ); FinishTo( wxPoint( cx + pos.x, cy + pos.y ) ); cx = 0; cy = deltaxy / 2; RotatePoint( &cx, &cy, orient ); Arc( wxPoint( cx + pos.x, cy + pos.y ), orient + 1800, orient + 3600, radius, NO_FILL ); cx = 0; cy = -deltaxy / 2; RotatePoint( &cx, &cy, orient ); Arc( wxPoint( cx + pos.x, cy + pos.y ), orient, orient + 1800, radius, NO_FILL ); }