Minor plotter code improvements.

This commit is contained in:
Wayne Stambaugh 2021-06-07 14:31:53 -04:00
parent 4c293e0936
commit 08e8b17029
12 changed files with 668 additions and 613 deletions

View File

@ -8,8 +8,8 @@
* *
* Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net> * Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -41,9 +41,8 @@
/** /**
* Function GetPensizeForBold * @param aTextSize is the char size (height or width).
* @return the "best" value for a pen size to draw/plot a bold text * @return the "best" value for a pen size to draw/plot a bold text.
* @param aTextSize = the char size (height or width)
*/ */
int GetPenSizeForBold( int aTextSize ) int GetPenSizeForBold( int aTextSize )
{ {
@ -58,13 +57,13 @@ int GetPenSizeForNormal( int aTextSize )
/** /**
* Function Clamp_Text_PenSize
* Don't allow text to become cluttered up in its own fatness. Bold fonts are generally around * Don't allow text to become cluttered up in its own fatness. Bold fonts are generally around
* aSize/5 in width, so we limit them to aSize/4, and normal text to aSize/6. * aSize/5 in width, so we limit them to aSize/4, and normal text to aSize/6.
* @param aPenSize = the pen size to clamp *
* @param aSize the char size (height or width) * @param aPenSize is the pen size to clamp.
* @param aBold = true if text accept bold pen size * @param aSize is the character size (height or width).
* @return the max pen size allowed * @param aBold use true if text accept bold pen size.
* @return the max pen size allowed.
*/ */
int Clamp_Text_PenSize( int aPenSize, int aSize, bool aBold ) int Clamp_Text_PenSize( int aPenSize, int aSize, bool aBold )
{ {
@ -105,27 +104,27 @@ int GraphicTextWidth( const wxString& aText, const wxSize& aSize, bool aItalic,
/** /**
* Function GRText * Draw a graphic text (like footprint texts).
* Draw a graphic text (like footprint texts) *
* @param aDC = the current Device Context. NULL if draw within a 3D GL Canvas * @param aDC is the current Device Context. NULL if draw within a 3D GL Canvas.
* @param aPos = text position (according to h_justify, v_justify) * @param aPos is the text position (according to h_justify, v_justify).
* @param aColor (COLOR4D) = text color * @param aColor is the text color.
* @param aText = text to draw * @param aText is the text to draw.
* @param aOrient = angle in 0.1 degree * @param aOrient is the angle in 0.1 degree.
* @param aSize = text size (size.x or size.y can be < 0 for mirrored texts) * @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
* @param aH_justify = horizontal justification (Left, center, right) * @param aH_justify is the horizontal justification (Left, center, right).
* @param aV_justify = vertical justification (bottom, center, top) * @param aV_justify is the vertical justification (bottom, center, top).
* @param aWidth = line width (pen width) (use default width if aWidth = 0) * @param aWidth is the line width (pen width) (use default width if aWidth = 0).
* if width < 0 : draw segments in sketch mode, width = abs(width) * if width < 0 : draw segments in sketch mode, width = abs(width)
* Use a value min(aSize.x, aSize.y) / 5 for a bold text * Use a value min(aSize.x, aSize.y) / 5 for a bold text.
* @param aItalic = true to simulate an italic font * @param aItalic is the true to simulate an italic font.
* @param aBold = true to use a bold font. Useful only with default width value (aWidth = 0) * @param aBold use true to use a bold font. Useful only with default width value (aWidth = 0).
* @param aCallback( int x0, int y0, int xf, int yf, void* aData ) is a function called * @param aCallback( int x0, int y0, int xf, int yf, void* aData ) is a function called
* (if non null) to draw each segment. used to draw 3D texts or for plotting. * (if non null) to draw each segment. used to draw 3D texts or for plotting.
* NULL for normal drawings * NULL for normal drawings
* @param aCallbackData = is the auxiliary parameter aData for the callback function. * @param aCallbackData is the auxiliary parameter aData for the callback function.
* can be nullptr if no auxiliary parameter is needed * can be nullptr if no auxiliary parameter is needed
* @param aPlotter = a pointer to a PLOTTER instance, when this function is used to plot * @param aPlotter is a PLOTTER instance, when this function is used to plot
* the text. NULL to draw this text. * the text. NULL to draw this text.
*/ */
void GRText( wxDC* aDC, const wxPoint& aPos, COLOR4D aColor, const wxString& aText, void GRText( wxDC* aDC, const wxPoint& aPos, COLOR4D aColor, const wxString& aText,
@ -168,12 +167,11 @@ void GRText( wxDC* aDC, const wxPoint& aPos, COLOR4D aColor, const wxString& aTe
basic_gal.m_DC = aDC; basic_gal.m_DC = aDC;
basic_gal.m_Color = aColor; basic_gal.m_Color = aColor;
basic_gal.SetClipBox( nullptr ); basic_gal.SetClipBox( nullptr );
basic_gal.StrokeText( aText, VECTOR2D( aPos ), aOrient * M_PI/1800 ); basic_gal.StrokeText( aText, VECTOR2D( aPos ), aOrient * M_PI/1800 );
} }
void GRHaloText( wxDC * aDC, const wxPoint &aPos, COLOR4D aBgColor, COLOR4D aColor1, void GRHaloText( wxDC* aDC, const wxPoint &aPos, COLOR4D aBgColor, COLOR4D aColor1,
COLOR4D aColor2, const wxString &aText, double aOrient, const wxSize &aSize, COLOR4D aColor2, const wxString &aText, double aOrient, const wxSize &aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify,
int aWidth, bool aItalic, bool aBold, int aWidth, bool aItalic, bool aBold,
@ -200,24 +198,24 @@ void GRHaloText( wxDC * aDC, const wxPoint &aPos, COLOR4D aBgColor, COLOR4D aCol
/** /**
* Function PLOTTER::Text * Same as GRText, but plot graphic text instead of draw it.
* same as GRText, but plot graphic text instead of draw it *
* @param aPos = text position (according to aH_justify, aV_justify) * @param aPos is the text position (according to aH_justify, aV_justify).
* @param aColor (COLOR4D) = text color * @param aColor is the text color.
* @param aText = text to draw * @param aText is the text to draw.
* @param aOrient = angle in 0.1 degree * @param aOrient is the angle in 0.1 degree.
* @param aSize = text size (size.x or size.y can be < 0 for mirrored texts) * @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
* @param aH_justify = horizontal justification (Left, center, right) * @param aH_justify is the horizontal justification (Left, center, right).
* @param aV_justify = vertical justification (bottom, center, top) * @param aV_justify is the vertical justification (bottom, center, top).
* @param aPenWidth = line width (if = 0, use plot default line width) * @param aPenWidth is the line width (if = 0, use plot default line width).
* @param aItalic = true to simulate an italic font * @param aItalic is the true to simulate an italic font.
* @param aBold = true to use a bold font Useful only with default width value (aWidth = 0) * @param aBold use 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 * @param aMultilineAllowed use true to plot text as multiline, otherwise single line.
* @param aData = a parameter used by some plotters in SetCurrentLineWidth(), * @param aData is a parameter used by some plotters in SetCurrentLineWidth(),
* not directly used here. * not directly used here.
*/ */
void PLOTTER::Text( const wxPoint& aPos, void PLOTTER::Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,

View File

@ -5,7 +5,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -115,7 +115,7 @@ static const char* getDXFLineType( PLOT_DASH_TYPE aType )
// A helper function to create a color name acceptable in DXF files // A helper function to create a color name acceptable in DXF files
// DXF files do not use a RGB definition // DXF files do not use a RGB definition
static wxString getDXFColorName( COLOR4D aColor ) static wxString getDXFColorName( const COLOR4D& aColor )
{ {
EDA_COLOR_T color = COLOR4D::FindNearestLegacyColor( int( aColor.r * 255 ), EDA_COLOR_T color = COLOR4D::FindNearestLegacyColor( int( aColor.r * 255 ),
int( aColor.g * 255 ), int( aColor.g * 255 ),
@ -144,11 +144,6 @@ void DXF_PLOTTER::SetUnits( DXF_UNITS aUnit )
} }
/**
* Set the scale/position for the DXF plot
* The DXF engine doesn't support line widths and mirroring. The output
* coordinate system is in the first quadrant (in mm)
*/
void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) double aScale, bool aMirror )
{ {
@ -172,9 +167,7 @@ void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
m_currentColor = COLOR4D::BLACK; m_currentColor = COLOR4D::BLACK;
} }
/**
* Opens the DXF plot with a skeleton header
*/
bool DXF_PLOTTER::StartPlot() bool DXF_PLOTTER::StartPlot()
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -404,10 +397,7 @@ bool DXF_PLOTTER::EndPlot()
} }
/** void DXF_PLOTTER::SetColor( const COLOR4D& color )
* The DXF exporter handles 'colors' as layers...
*/
void DXF_PLOTTER::SetColor( COLOR4D color )
{ {
if( ( m_colorMode ) if( ( m_colorMode )
|| ( color == COLOR4D::BLACK ) || ( color == COLOR4D::BLACK )
@ -421,9 +411,7 @@ void DXF_PLOTTER::SetColor( COLOR4D color )
} }
} }
/**
* DXF rectangle: fill not supported
*/
void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -435,17 +423,12 @@ void DXF_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, in
} }
/**
* DXF circle: full functionality; it even does 'fills' drawing a
* circle with a dual-arc polyline wide as the radius.
*
* I could use this trick to do other filled primitives
*/
void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, int width ) void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
double radius = userToDeviceSize( diameter / 2 ); double radius = userToDeviceSize( diameter / 2 );
DPOINT centre_dev = userToDeviceCoordinates( centre ); DPOINT centre_dev = userToDeviceCoordinates( centre );
if( radius > 0 ) if( radius > 0 )
{ {
wxString cname = getDXFColorName( m_currentColor ); wxString cname = getDXFColorName( m_currentColor );
@ -460,29 +443,23 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, i
if( fill == FILL_TYPE::FILLED_SHAPE ) if( fill == FILL_TYPE::FILLED_SHAPE )
{ {
double r = radius*0.5; double r = radius*0.5;
fprintf( m_outputFile, "0\nPOLYLINE\n"); fprintf( m_outputFile, "0\nPOLYLINE\n" );
fprintf( m_outputFile, "8\n%s\n66\n1\n70\n1\n", TO_UTF8( cname )); fprintf( m_outputFile, "8\n%s\n66\n1\n70\n1\n", TO_UTF8( cname ) );
fprintf( m_outputFile, "40\n%g\n41\n%g\n", radius, radius); fprintf( m_outputFile, "40\n%g\n41\n%g\n", radius, radius);
fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname )); fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ) );
fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n", fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
centre_dev.x-r, centre_dev.y ); centre_dev.x-r, centre_dev.y );
fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname )); fprintf( m_outputFile, "0\nVERTEX\n8\n%s\n", TO_UTF8( cname ) );
fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n", fprintf( m_outputFile, "10\n%g\n 20\n%g\n42\n1.0\n",
centre_dev.x+r, centre_dev.y ); centre_dev.x+r, centre_dev.y );
fprintf( m_outputFile, "0\nSEQEND\n"); fprintf( m_outputFile, "0\nSEQEND\n");
} }
} }
} }
/**
* DXF polygon: doesn't fill it but at least it close the filled ones
* DXF does not know thick outline.
* It does not know thick segments, therefore filled polygons with thick outline
* are converted to inflated polygon by aWidth/2
*/
void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
FILL_TYPE aFill, int aWidth, void * aData ) FILL_TYPE aFill, int aWidth, void* aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
@ -509,7 +486,6 @@ void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
return; return;
} }
// if the polygon outline has thickness, and is not filled // if the polygon outline has thickness, and is not filled
// (i.e. is a polyline) plot outlines with thick segments // (i.e. is a polyline) plot outlines with thick segments
if( aWidth > 0 && aFill == FILL_TYPE::NO_FILL ) if( aWidth > 0 && aFill == FILL_TYPE::NO_FILL )
@ -517,8 +493,7 @@ void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
MoveTo( aCornerList[0] ); MoveTo( aCornerList[0] );
for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
ThickSegment( aCornerList[ii-1], aCornerList[ii], ThickSegment( aCornerList[ii-1], aCornerList[ii], aWidth, FILLED, NULL );
aWidth, FILLED, NULL );
return; return;
} }
@ -591,6 +566,7 @@ void DXF_PLOTTER::PenTo( const wxPoint& pos, char plume )
{ {
return; return;
} }
DPOINT pos_dev = userToDeviceCoordinates( pos ); DPOINT pos_dev = userToDeviceCoordinates( pos );
DPOINT pen_lastpos_dev = userToDeviceCoordinates( m_penLastpos ); DPOINT pen_lastpos_dev = userToDeviceCoordinates( m_penLastpos );
@ -605,6 +581,7 @@ void DXF_PLOTTER::PenTo( const wxPoint& pos, char plume )
TO_UTF8( cname ), lname, TO_UTF8( cname ), lname,
pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y ); pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y );
} }
m_penLastpos = pos; m_penLastpos = pos;
} }
@ -628,6 +605,7 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int
const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 ); const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 );
cornerList.reserve( path.PointCount() ); cornerList.reserve( path.PointCount() );
for( int jj = 0; jj < path.PointCount(); jj++ ) for( int jj = 0; jj < path.PointCount(); jj++ )
cornerList.emplace_back( path.CPoint( jj ).x, path.CPoint( jj ).y ); cornerList.emplace_back( path.CPoint( jj ).x, path.CPoint( jj ).y );
@ -644,6 +622,7 @@ void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int
} }
} }
/* Plot an arc in DXF format /* Plot an arc in DXF format
* Filling is not supported * Filling is not supported
*/ */
@ -675,9 +654,7 @@ void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
StAngle / 10.0, EndAngle / 10.0 ); StAngle / 10.0, EndAngle / 10.0 );
} }
/**
* DXF oval pad: always done in sketch mode
*/
void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient, void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
OUTLINE_MODE trace_mode, void* aData ) OUTLINE_MODE trace_mode, void* aData )
{ {
@ -696,21 +673,14 @@ void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double
} }
/**
* DXF round pad: always done in sketch mode; it could be filled but it isn't
* pretty if other kinds of pad aren't...
*/
void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre,
OUTLINE_MODE trace_mode, void* aData ) OUTLINE_MODE trace_mode, void* aData )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
Circle( pos, diametre, FILL_TYPE::NO_FILL ); Circle( pos, diametre, FILL_TYPE::NO_FILL );
} }
/**
* DXF rectangular pad: always done in sketch mode
*/
void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
double orient, OUTLINE_MODE trace_mode, void* aData ) double orient, OUTLINE_MODE trace_mode, void* aData )
{ {
@ -723,6 +693,7 @@ void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
if( size.x < 0 ) if( size.x < 0 )
size.x = 0; size.x = 0;
if( size.y < 0 ) if( size.y < 0 )
size.y = 0; size.y = 0;
@ -739,6 +710,7 @@ void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
FinishTo( wxPoint( fx, fy ) ); FinishTo( wxPoint( fx, fy ) );
return; return;
} }
if( size.y == 0 ) if( size.y == 0 )
{ {
ox = pos.x - size.x; ox = pos.x - size.x;
@ -775,13 +747,14 @@ void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
FinishTo( wxPoint( ox, oy ) ); FinishTo( wxPoint( ox, oy ) );
} }
void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
int aCornerRadius, double aOrient, int aCornerRadius, double aOrient,
OUTLINE_MODE aTraceMode, void* aData ) OUTLINE_MODE aTraceMode, void* aData )
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius,
aCornerRadius, 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE ); 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE );
// TransformRoundRectToPolygon creates only one convex polygon // TransformRoundRectToPolygon creates only one convex polygon
SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
@ -812,9 +785,6 @@ void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
} }
/**
* DXF trapezoidal pad: only sketch mode is supported
*/
void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, OUTLINE_MODE aTrace_Mode, void* aData ) double aPadOrient, OUTLINE_MODE aTrace_Mode, void* aData )
{ {
@ -837,9 +807,8 @@ void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorner
} }
void DXF_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, void DXF_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, int aRadius, int aCornerCount,
int aRadius, int aCornerCount, double aOrient, OUTLINE_MODE aTraceMode, void* aData )
double aOrient, OUTLINE_MODE aTraceMode, void* aData )
{ {
// Do nothing // Do nothing
wxASSERT( 0 ); wxASSERT( 0 );
@ -847,10 +816,12 @@ void DXF_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos,
/** /**
* Checks if a given string contains non-ASCII characters. * Check if a given string contains non-ASCII characters.
* FIXME: the performance of this code is really poor, but in this case it can be *
* acceptable because the plot operation is not called very often. * @fixme The performance of this code is really poor, but in this case it can be
* @param string String to check * acceptable because the plot operation is not called very often.
*
* @param string String to check.
* @return true if it contains some non-ASCII character, false if all characters are * @return true if it contains some non-ASCII character, false if all characters are
* inside ASCII range (<=255). * inside ASCII range (<=255).
*/ */
@ -865,8 +836,9 @@ bool containsNonAsciiChars( const wxString& string )
return false; return false;
} }
void DXF_PLOTTER::Text( const wxPoint& aPos, void DXF_PLOTTER::Text( const wxPoint& aPos,
COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -901,6 +873,7 @@ void DXF_PLOTTER::Text( const wxPoint& aPos,
wxString cname = getDXFColorName( m_currentColor ); wxString cname = getDXFColorName( m_currentColor );
DPOINT size_dev = userToDeviceSize( aSize ); DPOINT size_dev = userToDeviceSize( aSize );
int h_code = 0, v_code = 0; int h_code = 0, v_code = 0;
switch( aH_justify ) switch( aH_justify )
{ {
case GR_TEXT_HJUSTIFY_LEFT: case GR_TEXT_HJUSTIFY_LEFT:
@ -913,6 +886,7 @@ void DXF_PLOTTER::Text( const wxPoint& aPos,
h_code = 2; h_code = 2;
break; break;
} }
switch( aV_justify ) switch( aV_justify )
{ {
case GR_TEXT_VJUSTIFY_TOP: case GR_TEXT_VJUSTIFY_TOP:
@ -1042,6 +1016,7 @@ void DXF_PLOTTER::Text( const wxPoint& aPos,
putc( ch, m_outputFile ); putc( ch, m_outputFile );
} }
} }
putc( '\n', m_outputFile ); putc( '\n', m_outputFile );
} }
} }

View File

@ -66,7 +66,8 @@
#define GBR_MACRO_FOR_CUSTOM_PAD_MAX_CORNER_COUNT 4990 #define GBR_MACRO_FOR_CUSTOM_PAD_MAX_CORNER_COUNT 4990
#define AM_FREEPOLY_BASENAME "FreePoly" #define AM_FREEPOLY_BASENAME "FreePoly"
// A helper function to compare 2 polygons: polygons are similar if they havve the same
// A helper function to compare 2 polygons: polygons are similar if they have the same
// number of vertices and each vertex coordinate are similar, i.e. if the difference // number of vertices and each vertex coordinate are similar, i.e. if the difference
// between coordinates is small ( <= margin to accept rounding issues coming from polygon // between coordinates is small ( <= margin to accept rounding issues coming from polygon
// geometric transforms like rotation // geometric transforms like rotation
@ -121,7 +122,7 @@ GERBER_PLOTTER::GERBER_PLOTTER()
void GERBER_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, void GERBER_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) double aScale, bool aMirror )
{ {
wxASSERT( aMirror == false ); wxASSERT( aMirror == false );
m_plotMirror = false; m_plotMirror = false;
@ -130,6 +131,7 @@ void GERBER_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
m_plotScale = 1; // Plot scale is *always* 1.0 m_plotScale = 1; // Plot scale is *always* 1.0
m_IUsPerDecimil = aIusPerDecimil; m_IUsPerDecimil = aIusPerDecimil;
// gives now a default value to iuPerDeviceUnit (because the units of the caller is now known) // gives now a default value to iuPerDeviceUnit (because the units of the caller is now known)
// which could be modified later by calling SetGerberCoordinatesFormat() // which could be modified later by calling SetGerberCoordinatesFormat()
m_iuPerDeviceUnit = pow( 10.0, m_gerberUnitFmt ) / ( m_IUsPerDecimil * 10000.0 ); m_iuPerDeviceUnit = pow( 10.0, m_gerberUnitFmt ) / ( m_IUsPerDecimil * 10000.0 );
@ -240,7 +242,8 @@ bool GERBER_PLOTTER::StartPlot()
m_hasApertureRoundRect = false; // true is at least one round rect aperture is in use m_hasApertureRoundRect = false; // true is at least one round rect aperture is in use
m_hasApertureRotOval = false; // true is at least one oval rotated aperture is in use m_hasApertureRotOval = false; // true is at least one oval rotated aperture is in use
m_hasApertureRotRect = false; // true is at least one rect. rotated aperture is in use m_hasApertureRotRect = false; // true is at least one rect. rotated aperture is in use
m_hasApertureOutline4P = false; // true is at least one rotated rect/trapezoid aperture is in use m_hasApertureOutline4P = false; // true is at least one rotated rect/trapezoid aperture
// is in use
m_hasApertureChamferedRect = false; // true is at least one chamfered rect is in use m_hasApertureChamferedRect = false; // true is at least one chamfered rect is in use
m_am_freepoly_list.ClearList(); m_am_freepoly_list.ClearList();
@ -248,7 +251,8 @@ bool GERBER_PLOTTER::StartPlot()
finalFile = m_outputFile; // the actual gerber file will be created later finalFile = m_outputFile; // the actual gerber file will be created later
// Create a temp file in system temp to avoid potential network share buffer issues for the final read and save // Create a temp file in system temp to avoid potential network share buffer issues for
// the final read and save.
m_workFilename = wxFileName::CreateTempFileName( "" ); m_workFilename = wxFileName::CreateTempFileName( "" );
workFile = wxFopen( m_workFilename, wxT( "wt" )); workFile = wxFopen( m_workFilename, wxT( "wt" ));
m_outputFile = workFile; m_outputFile = workFile;
@ -278,6 +282,7 @@ bool GERBER_PLOTTER::StartPlot()
m_gerberUnitInch ? "inch" : "mm" ); m_gerberUnitInch ? "inch" : "mm" );
wxString Title = m_creator + wxT( " " ) + GetBuildVersion(); wxString Title = m_creator + wxT( " " ) + GetBuildVersion();
// In gerber files, ASCII7 chars only are allowed. // In gerber files, ASCII7 chars only are allowed.
// So use a ISO date format (using a space as separator between date and time), // So use a ISO date format (using a space as separator between date and time),
// not a localized date format // not a localized date format
@ -366,7 +371,7 @@ bool GERBER_PLOTTER::EndPlot()
if( m_am_freepoly_list.AmCount() ) if( m_am_freepoly_list.AmCount() )
{ {
// apertude sizes are in inch or mm, regardless the // aperture sizes are in inch or mm, regardless the
// coordinates format // coordinates format
double fscale = 0.0001 * m_plotScale / m_IUsPerDecimil; // inches double fscale = 0.0001 * m_plotScale / m_IUsPerDecimil; // inches
@ -443,12 +448,12 @@ int GERBER_PLOTTER::GetOrCreateAperture( const wxSize& aSize, int aRadius, doubl
int GERBER_PLOTTER::GetOrCreateAperture( const std::vector<wxPoint>& aCorners, double aRotDegree, int GERBER_PLOTTER::GetOrCreateAperture( const std::vector<wxPoint>& aCorners, double aRotDegree,
APERTURE::APERTURE_TYPE aType, int aApertureAttribute ) APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
{ {
int last_D_code = 9; int last_D_code = 9;
// For APERTURE::AM_FREE_POLYGON aperture macros, we need to create the macro // For APERTURE::AM_FREE_POLYGON aperture macros, we need to create the macro
// on the fly, because due to the fact the vertice count is not a constant we // on the fly, because due to the fact the vertex count is not a constant we
// cannot create a static definition. // cannot create a static definition.
if( APERTURE::AM_FREE_POLYGON == aType ) if( APERTURE::AM_FREE_POLYGON == aType )
{ {
@ -496,8 +501,7 @@ int GERBER_PLOTTER::GetOrCreateAperture( const std::vector<wxPoint>& aCorners, d
void GERBER_PLOTTER::selectAperture( const wxSize& aSize, int aRadius, double aRotDegree, void GERBER_PLOTTER::selectAperture( const wxSize& aSize, int aRadius, double aRotDegree,
APERTURE::APERTURE_TYPE aType, APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
int aApertureAttribute )
{ {
bool change = ( m_currentApertureIdx < 0 ) || bool change = ( m_currentApertureIdx < 0 ) ||
( m_apertures[m_currentApertureIdx].m_Type != aType ) || ( m_apertures[m_currentApertureIdx].m_Type != aType ) ||
@ -519,7 +523,7 @@ void GERBER_PLOTTER::selectAperture( const wxSize& aSize, int aRadius, double aR
void GERBER_PLOTTER::selectAperture( const std::vector<wxPoint>& aCorners, double aRotDegree, void GERBER_PLOTTER::selectAperture( const std::vector<wxPoint>& aCorners, double aRotDegree,
APERTURE::APERTURE_TYPE aType, int aApertureAttribute ) APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
{ {
bool change = ( m_currentApertureIdx < 0 ) || bool change = ( m_currentApertureIdx < 0 ) ||
( m_apertures[m_currentApertureIdx].m_Type != aType ) || ( m_apertures[m_currentApertureIdx].m_Type != aType ) ||
@ -552,14 +556,14 @@ void GERBER_PLOTTER::selectAperture( const std::vector<wxPoint>& aCorners, doubl
void GERBER_PLOTTER::selectAperture( int aDiameter, double aPolygonRotation, void GERBER_PLOTTER::selectAperture( int aDiameter, double aPolygonRotation,
APERTURE::APERTURE_TYPE aType, int aApertureAttribute ) APERTURE::APERTURE_TYPE aType, int aApertureAttribute )
{ {
// Pick an existing aperture or create a new one, matching the // Pick an existing aperture or create a new one, matching the
// aDiameter, aPolygonRotation, type and attributes for type = // aDiameter, aPolygonRotation, type and attributes for type =
// AT_REGULAR_POLY3 to AT_REGULAR_POLY12 // AT_REGULAR_POLY3 to AT_REGULAR_POLY12
wxASSERT( aType>= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY3 && wxASSERT( aType>= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY3 &&
aType <= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY12 ); aType <= APERTURE::APERTURE_TYPE::AT_REGULAR_POLY12 );
wxSize size( aDiameter, (int)( aPolygonRotation * 1000.0 ) ); wxSize size( aDiameter, (int)( aPolygonRotation * 1000.0 ) );
selectAperture( wxSize( 0, 0), aDiameter/2, aPolygonRotation, aType, aApertureAttribute ); selectAperture( wxSize( 0, 0), aDiameter/2, aPolygonRotation, aType, aApertureAttribute );
@ -579,7 +583,7 @@ void GERBER_PLOTTER::writeApertureList()
// Init // Init
for( APERTURE& tool : m_apertures ) for( APERTURE& tool : m_apertures )
{ {
// apertude sizes are in inch or mm, regardless the // aperture sizes are in inch or mm, regardless the
// coordinates format // coordinates format
double fscale = 0.0001 * m_plotScale / m_IUsPerDecimil; // inches double fscale = 0.0001 * m_plotScale / m_IUsPerDecimil; // inches
@ -602,7 +606,7 @@ void GERBER_PLOTTER::writeApertureList()
exponential syntax is *not* allowed and the decimal point should exponential syntax is *not* allowed and the decimal point should
also be always inserted. So the %g format is ruled out, but %f is fine also be always inserted. So the %g format is ruled out, but %f is fine
(the # modifier forces the decimal point). Sadly the %f formatter (the # modifier forces the decimal point). Sadly the %f formatter
can't remove trailing zeros but thats not a problem, since nothing can't remove trailing zeros but that's not a problem, since nothing
forbid it (the file is only slightly longer) */ forbid it (the file is only slightly longer) */
switch( tool.m_Type ) switch( tool.m_Type )
@ -641,7 +645,7 @@ void GERBER_PLOTTER::writeApertureList()
break; break;
case APERTURE::AM_ROUND_RECT: // Aperture macro for round rect pads case APERTURE::AM_ROUND_RECT: // Aperture macro for round rect pads
{ {
// The aperture macro needs coordinates of the centers of the 4 corners // The aperture macro needs coordinates of the centers of the 4 corners
std::vector<VECTOR2I> corners; std::vector<VECTOR2I> corners;
wxSize half_size( tool.m_Size.x/2-tool.m_Radius, tool.m_Size.y/2-tool.m_Radius ); wxSize half_size( tool.m_Size.x/2-tool.m_Radius, tool.m_Size.y/2-tool.m_Radius );
@ -668,7 +672,7 @@ void GERBER_PLOTTER::writeApertureList()
} }
sprintf( cbuf, "0*%%\n" ); sprintf( cbuf, "0*%%\n" );
} }
break; break;
case APERTURE::AM_ROT_RECT: // Aperture macro for rotated rect pads case APERTURE::AM_ROT_RECT: // Aperture macro for rotated rect pads
@ -716,9 +720,9 @@ void GERBER_PLOTTER::writeApertureList()
case APERTURE::AM_ROTATED_OVAL: // Aperture macro for rotated oval pads case APERTURE::AM_ROTATED_OVAL: // Aperture macro for rotated oval pads
// (not rotated is a primitive) // (not rotated is a primitive)
// m_Size.x = full lenght; m_Size.y = width, and the macro aperure expects // m_Size.x = full length; m_Size.y = width, and the macro aperture expects
// the position of ends // the position of ends
{ {
// the seg_len is the distance between the 2 circle centers // the seg_len is the distance between the 2 circle centers
int seg_len = tool.m_Size.x - tool.m_Size.y; int seg_len = tool.m_Size.x - tool.m_Size.y;
// Center of the circle on the segment start point: // Center of the circle on the segment start point:
@ -733,21 +737,21 @@ void GERBER_PLOTTER::writeApertureList()
tool.m_Size.y * fscale, // width tool.m_Size.y * fscale, // width
start.x * fscale, -start.y * fscale, // X,Y corner start pos start.x * fscale, -start.y * fscale, // X,Y corner start pos
end.x * fscale, -end.y * fscale ); // X,Y cornerend pos end.x * fscale, -end.y * fscale ); // X,Y cornerend pos
} }
break; break;
case APERTURE::AM_FREE_POLYGON: case APERTURE::AM_FREE_POLYGON:
{ {
// Find the aperture macro name in the list of aperture macro // Find the aperture macro name in the list of aperture macro
// created on the fly for this polygon: // created on the fly for this polygon:
int idx = m_am_freepoly_list.FindAm( tool.m_Corners ); int idx = m_am_freepoly_list.FindAm( tool.m_Corners );
// Write DCODE id ( "%ADDxx" is already in buffer) and rotation // Write DCODE id ( "%ADDxx" is already in buffer) and rotation
// the full line is something like :%ADD12FreePoly1,45.000000*% // the full line is something like :%ADD12FreePoly1,45.000000*%
sprintf( cbuf, "%s%d,%#f*%%\n", AM_FREEPOLY_BASENAME, idx, tool.m_Rotation ); sprintf( cbuf, "%s%d,%#f*%%\n", AM_FREEPOLY_BASENAME, idx, tool.m_Rotation );
}
break; break;
} }
}
buffer += cbuf; buffer += cbuf;
fputs( buffer.c_str(), m_outputFile ); fputs( buffer.c_str(), m_outputFile );
@ -826,6 +830,7 @@ void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAn
plotArc( aCenter, aStAngle, aEndAngle, aRadius, false ); plotArc( aCenter, aStAngle, aEndAngle, aRadius, false );
} }
void GERBER_PLOTTER::Arc( const SHAPE_ARC& aArc ) void GERBER_PLOTTER::Arc( const SHAPE_ARC& aArc )
{ {
SetCurrentLineWidth( aArc.GetWidth() ); SetCurrentLineWidth( aArc.GetWidth() );
@ -860,12 +865,12 @@ void GERBER_PLOTTER::plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion )
KiROUND( devEnd.x ), KiROUND( devEnd.y ), KiROUND( devEnd.x ), KiROUND( devEnd.y ),
KiROUND( devCenter.x ), KiROUND( devCenter.y ) ); KiROUND( devCenter.x ), KiROUND( devCenter.y ) );
fprintf( m_outputFile, "G01*\n" ); // Back to linear interpol (perhaps useless here). fprintf( m_outputFile, "G01*\n" ); // Back to linear interpolate (perhaps useless here).
} }
void GERBER_PLOTTER::plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle, void GERBER_PLOTTER::plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
int aRadius, bool aPlotInRegion ) int aRadius, bool aPlotInRegion )
{ {
wxPoint start, end; wxPoint start, end;
start.x = aCenter.x + KiROUND( cosdecideg( aRadius, aStAngle ) ); start.x = aCenter.x + KiROUND( cosdecideg( aRadius, aStAngle ) );
@ -892,12 +897,11 @@ void GERBER_PLOTTER::plotArc( const wxPoint& aCenter, double aStAngle, double aE
KiROUND( devEnd.x ), KiROUND( devEnd.y ), KiROUND( devEnd.x ), KiROUND( devEnd.y ),
KiROUND( devCenter.x ), KiROUND( devCenter.y ) ); KiROUND( devCenter.x ), KiROUND( devCenter.y ) );
fprintf( m_outputFile, "G01*\n" ); // Back to linear interpol (perhaps useless here). fprintf( m_outputFile, "G01*\n" ); // Back to linear interpolate (perhaps useless here).
} }
void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aData )
void* aData )
{ {
if( aPoly.PointCount() <= 2 ) if( aPoly.PointCount() <= 2 )
return; return;
@ -934,8 +938,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly,
} }
void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList, void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList, void* aData )
void* aData )
{ {
if( aCornerList.size() <= 2 ) if( aCornerList.size() <= 2 )
return; return;
@ -971,8 +974,9 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList
} }
} }
void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly,
FILL_TYPE aFill, int aWidth, void* aData ) void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_TYPE aFill, int aWidth,
void* aData )
{ {
if( aPoly.CPoints().size() <= 1 ) if( aPoly.CPoints().size() <= 1 )
return; return;
@ -1100,7 +1104,7 @@ void GERBER_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
void GERBER_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width, void GERBER_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width,
OUTLINE_MODE tracemode, void* aData ) OUTLINE_MODE tracemode, void* aData )
{ {
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
@ -1130,15 +1134,17 @@ void GERBER_PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double End
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
if( tracemode == FILLED ) if( tracemode == FILLED )
{
Arc( centre, StAngle, EndAngle, radius, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Arc( centre, StAngle, EndAngle, radius, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH );
}
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
Arc( centre, StAngle, EndAngle, Arc( centre, StAngle, EndAngle,
radius - ( width - m_currentPenWidth ) / 2, FILL_TYPE::NO_FILL, radius - ( width - m_currentPenWidth ) / 2, FILL_TYPE::NO_FILL,
DO_NOT_SET_LINE_WIDTH ); DO_NOT_SET_LINE_WIDTH );
Arc( centre, StAngle, EndAngle, radius + ( width - m_currentPenWidth ) / 2, FILL_TYPE::NO_FILL, Arc( centre, StAngle, EndAngle, radius + ( width - m_currentPenWidth ) / 2,
DO_NOT_SET_LINE_WIDTH ); FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH );
} }
} }
@ -1153,14 +1159,16 @@ void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
if( tracemode == FILLED ) if( tracemode == FILLED )
{
Rect( p1, p2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Rect( p1, p2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH );
}
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
wxPoint offsetp1( p1.x - (width - m_currentPenWidth) / 2, wxPoint offsetp1( p1.x - (width - m_currentPenWidth) / 2,
p1.y - (width - m_currentPenWidth) / 2 ); p1.y - (width - m_currentPenWidth) / 2 );
wxPoint offsetp2( p2.x + (width - m_currentPenWidth) / 2, wxPoint offsetp2( p2.x + (width - m_currentPenWidth) / 2,
p2.y + (width - m_currentPenWidth) / 2 ); p2.y + (width - m_currentPenWidth) / 2 );
Rect( offsetp1, offsetp2, FILL_TYPE::NO_FILL, -1 ); Rect( offsetp1, offsetp2, FILL_TYPE::NO_FILL, -1 );
offsetp1.x += (width - m_currentPenWidth); offsetp1.x += (width - m_currentPenWidth);
offsetp1.y += (width - m_currentPenWidth); offsetp1.y += (width - m_currentPenWidth);
@ -1172,7 +1180,7 @@ void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width, void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width,
OUTLINE_MODE tracemode, void* aData ) OUTLINE_MODE tracemode, void* aData )
{ {
GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData ); GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
SetCurrentLineWidth( width, gbr_metadata ); SetCurrentLineWidth( width, gbr_metadata );
@ -1181,7 +1189,9 @@ void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width,
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
if( tracemode == FILLED ) if( tracemode == FILLED )
{
Circle( pos, diametre, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Circle( pos, diametre, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH );
}
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata );
@ -1205,7 +1215,7 @@ void GERBER_PLOTTER::FilledCircle( const wxPoint& pos, int diametre,
if( tracemode == FILLED ) if( tracemode == FILLED )
{ {
// Draw a circle of diameter = diametre/2 with a line thickness = radius, // Draw a circle of diameter = diameter/2 with a line thickness = radius,
// To create a filled circle // To create a filled circle
SetCurrentLineWidth( diametre/2, gbr_metadata ); SetCurrentLineWidth( diametre/2, gbr_metadata );
Circle( pos, diametre/2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH ); Circle( pos, diametre/2, FILL_TYPE::NO_FILL, DO_NOT_SET_LINE_WIDTH );
@ -1305,7 +1315,7 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
// Draw the oval as round rect pad with a radius = 50% min size) // Draw the oval as round rect pad with a radius = 50% min size)
// In gerber file, it will be drawn as a region with arcs, and can be // In gerber file, it will be drawn as a region with arcs, and can be
// detected as pads (similar to a flashed pad) // detected as pads (similar to a flashed pad)
FlashPadRoundRect( pos, aSize, std::min( aSize.x, aSize.y ) /2, FlashPadRoundRect( pos, aSize, std::min( aSize.x, aSize.y ) / 2,
orient, FILLED, aData ); orient, FILLED, aData );
} }
else // Non filled shape: plot outlines: else // Non filled shape: plot outlines:
@ -1419,8 +1429,8 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
if( aTraceMode != FILLED ) if( aTraceMode != FILLED )
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius,
aCornerRadius, 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE ); 0.0, 0, GetPlotterArcHighDef(), ERROR_INSIDE );
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata );
outline.Inflate( -GetCurrentLineWidth()/2, 16 ); outline.Inflate( -GetCurrentLineWidth()/2, 16 );
@ -1458,6 +1468,7 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
emitDcode( pos_dev, 3 ); emitDcode( pos_dev, 3 );
return; return;
} }
// A Pad RoundRect is plotted as a Gerber region. // A Pad RoundRect is plotted as a Gerber region.
// Initialize region metadata: // Initialize region metadata:
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
@ -1605,12 +1616,13 @@ void GERBER_PLOTTER::plotRoundRectAsRegion( const wxPoint& aRectCenter, const wx
if( aCornerRadius ) // Guard: ensure we do not create arcs with radius = 0 if( aCornerRadius ) // Guard: ensure we do not create arcs with radius = 0
{ {
// LineTo( rr_edge.m_end ); // made in plotArc() // LineTo( rr_edge.m_end ); // made in plotArc()
plotArc( rr_edge.m_center, plotArc( rr_edge.m_center, rr_edge.m_arc_angle_start,
rr_edge.m_arc_angle_start, rr_edge.m_arc_angle_start+arc_angle, rr_edge.m_arc_angle_start+arc_angle, aCornerRadius, true );
aCornerRadius, true );
} }
else else
{
LineTo( rr_edge.m_end ); LineTo( rr_edge.m_end );
}
} }
fputs( "G37*\n", m_outputFile ); // Close region fputs( "G37*\n", m_outputFile ); // Close region
@ -1651,7 +1663,9 @@ void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize
cornerList.push_back( cornerList[0] ); cornerList.push_back( cornerList[0] );
if( aTraceMode == SKETCH ) if( aTraceMode == SKETCH )
{
PlotPoly( cornerList, FILL_TYPE::NO_FILL, GetCurrentLineWidth(), &gbr_metadata ); PlotPoly( cornerList, FILL_TYPE::NO_FILL, GetCurrentLineWidth(), &gbr_metadata );
}
else else
{ {
#ifdef GBR_USE_MACROS_FOR_CUSTOM_PAD #ifdef GBR_USE_MACROS_FOR_CUSTOM_PAD
@ -1684,9 +1698,9 @@ void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize
void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const wxSize& aPadSize, void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const wxSize& aPadSize,
int aCornerRadius, double aChamferRatio, int aCornerRadius, double aChamferRatio,
int aChamferPositions, int aChamferPositions, double aPadOrient,
double aPadOrient, OUTLINE_MODE aPlotMode, void* aData ) OUTLINE_MODE aPlotMode, void* aData )
{ {
GBR_METADATA gbr_metadata; GBR_METADATA gbr_metadata;
@ -1726,7 +1740,9 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const w
{ {
#ifdef GBR_USE_MACROS_FOR_CHAMFERED_ROUND_RECT #ifdef GBR_USE_MACROS_FOR_CHAMFERED_ROUND_RECT
if( m_gerberDisableApertMacros ) if( m_gerberDisableApertMacros )
{
PlotGerberRegion( cornerList, &gbr_metadata ); PlotGerberRegion( cornerList, &gbr_metadata );
}
else else
{ {
// An AM will be created. the shape must be in position 0,0 and orientation 0 // An AM will be created. the shape must be in position 0,0 and orientation 0
@ -1859,10 +1875,9 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo
} }
void GERBER_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, void GERBER_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter,
int aDiameter, int aCornerCount, int aCornerCount, double aOrient,
double aOrient, OUTLINE_MODE aTraceMode, OUTLINE_MODE aTraceMode, void* aData )
void* aData )
{ {
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData ); GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
@ -1909,7 +1924,7 @@ void GERBER_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos,
} }
void GERBER_PLOTTER::Text( const wxPoint& aPos, const COLOR4D aColor, void GERBER_PLOTTER::Text( const wxPoint& aPos, const COLOR4D& aColor,
const wxString& aText, double aOrient, const wxSize& aSize, const wxString& aText, double aOrient, const wxSize& aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_HJUSTIFY_T aH_justify,
enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic,
@ -1961,8 +1976,7 @@ void APER_MACRO_FREEPOLY::Format( FILE * aOutput, double aIu2GbrMacroUnit )
fprintf( aOutput, "%#f,%#f,", fprintf( aOutput, "%#f,%#f,",
m_Corners[jj].x * aIu2GbrMacroUnit, -m_Corners[jj].y * aIu2GbrMacroUnit ); m_Corners[jj].x * aIu2GbrMacroUnit, -m_Corners[jj].y * aIu2GbrMacroUnit );
if( curr_line_count_max >= 0 if( curr_line_count_max >= 0 && ++curr_line_corner_count >= curr_line_count_max )
&& ++curr_line_corner_count >= curr_line_count_max )
{ {
fprintf( aOutput, "\n" ); fprintf( aOutput, "\n" );
curr_line_corner_count = 0; curr_line_corner_count = 0;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -239,6 +239,7 @@ void HPGL_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
m_plotScale = aScale; m_plotScale = aScale;
m_IUsPerDecimil = aIusPerDecimil; m_IUsPerDecimil = aIusPerDecimil;
m_iuPerDeviceUnit = PLUsPERDECIMIL / aIusPerDecimil; m_iuPerDeviceUnit = PLUsPERDECIMIL / aIusPerDecimil;
/* Compute the paper size in IUs */ /* Compute the paper size in IUs */
m_paperSize = m_pageInfo.GetSizeMils(); m_paperSize = m_pageInfo.GetSizeMils();
m_paperSize.x *= 10.0 * aIusPerDecimil; m_paperSize.x *= 10.0 * aIusPerDecimil;
@ -253,9 +254,6 @@ void HPGL_PLOTTER::SetTargetChordLength( double chord_len )
} }
/**
* At the start of the HPGL plot pen speed and number are requested
*/
bool HPGL_PLOTTER::StartPlot() bool HPGL_PLOTTER::StartPlot()
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -269,9 +267,6 @@ bool HPGL_PLOTTER::StartPlot()
} }
/**
* HPGL end of plot: sort and emit graphics, pen return and release
*/
bool HPGL_PLOTTER::EndPlot() bool HPGL_PLOTTER::EndPlot()
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -368,13 +363,14 @@ bool HPGL_PLOTTER::EndPlot()
{ {
loc = item.loc_end; loc = item.loc_end;
} }
fputs( "\n", m_outputFile ); fputs( "\n", m_outputFile );
} }
} }
fputs( "PU;PA;SP0;\n", m_outputFile ); fputs( "PU;PA;SP0;\n", m_outputFile );
fclose( m_outputFile ); fclose( m_outputFile );
m_outputFile = NULL; m_outputFile = nullptr;
return true; return true;
} }
@ -384,6 +380,7 @@ void HPGL_PLOTTER::SetPenDiameter( double diameter )
penDiameter = diameter; penDiameter = diameter;
} }
void HPGL_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width ) void HPGL_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -406,9 +403,7 @@ void HPGL_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, i
} }
// HPGL circle void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill, int width )
void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill,
int width )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
double radius = userToDeviceSize( diameter / 2 ); double radius = userToDeviceSize( diameter / 2 );
@ -454,12 +449,8 @@ void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_TYPE fill,
} }
/** void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_TYPE aFill,
* HPGL polygon: int aWidth, void* aData )
*/
void HPGL_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
FILL_TYPE aFill, int aWidth, void * aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
@ -551,9 +542,6 @@ void HPGL_PLOTTER::PenTo( const wxPoint& pos, char plume )
} }
/**
* HPGL supports dashed lines
*/
void HPGL_PLOTTER::SetDash( PLOT_DASH_TYPE dashed ) void HPGL_PLOTTER::SetDash( PLOT_DASH_TYPE dashed )
{ {
dashType = dashed; dashType = dashed;
@ -579,14 +567,6 @@ void HPGL_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end,
} }
/* Plot an arc:
* Center = center coord
* Stangl, endAngle = angle of beginning and end
* Radius = radius of the arc
* Command
* PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, NbSegm; PU;
* Or PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, PU;
*/
void HPGL_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void HPGL_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_TYPE fill, int width )
{ {
@ -637,8 +617,6 @@ void HPGL_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle,
} }
/* Plot oval pad.
*/
void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient, void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient,
OUTLINE_MODE trace_mode, void* aData ) OUTLINE_MODE trace_mode, void* aData )
{ {
@ -646,9 +624,7 @@ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double
int deltaxy, cx, cy; int deltaxy, cx, cy;
wxSize size( aSize ); wxSize size( aSize );
/* The pad will be drawn as an oblong shape with size.y > size.x // The pad will be drawn as an oblong shape with size.y > size.x (Oval vertical orientation 0).
* (Oval vertical orientation 0)
*/
if( size.x > size.y ) if( size.x > size.y )
{ {
std::swap( size.x, size.y ); std::swap( size.x, size.y );
@ -675,8 +651,6 @@ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double
} }
/* Plot round pad or via.
*/
void HPGL_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, void HPGL_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre,
OUTLINE_MODE trace_mode, void* aData ) OUTLINE_MODE trace_mode, void* aData )
{ {
@ -759,8 +733,8 @@ void HPGL_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize,
void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
int aCornerRadius, double aOrient, int aCornerRadius, double aOrient,
OUTLINE_MODE aTraceMode, void* aData ) OUTLINE_MODE aTraceMode, void* aData )
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
@ -841,9 +815,8 @@ void HPGL_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorne
} }
void HPGL_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, void HPGL_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, int aRadius, int aCornerCount,
int aRadius, int aCornerCount, double aOrient, OUTLINE_MODE aTraceMode, void* aData )
double aOrient, OUTLINE_MODE aTraceMode, void* aData )
{ {
// Do nothing // Do nothing
wxASSERT( 0 ); wxASSERT( 0 );
@ -884,6 +857,7 @@ bool HPGL_PLOTTER::startOrAppendItem( DPOINT location, wxString const& content )
} }
} }
void HPGL_PLOTTER::sortItems( std::list<HPGL_ITEM>& items ) void HPGL_PLOTTER::sortItems( std::list<HPGL_ITEM>& items )
{ {
if( items.size() < 2 ) if( items.size() < 2 )
@ -932,6 +906,7 @@ void HPGL_PLOTTER::sortItems( std::list<HPGL_ITEM>& items )
} }
double const dist = dpoint_dist( last_item.loc_end, search_it->loc_start ); double const dist = dpoint_dist( last_item.loc_end, search_it->loc_start );
if( dist < best_dist ) if( dist < best_dist )
{ {
best_it = search_it; best_it = search_it;
@ -948,6 +923,7 @@ void HPGL_PLOTTER::sortItems( std::list<HPGL_ITEM>& items )
items.splice( items.begin(), target ); items.splice( items.begin(), target );
} }
const char* HPGL_PLOTTER::lineTypeCommand( PLOT_DASH_TYPE linetype ) const char* HPGL_PLOTTER::lineTypeCommand( PLOT_DASH_TYPE linetype )
{ {
switch( linetype ) switch( linetype )
@ -967,6 +943,7 @@ const char* HPGL_PLOTTER::lineTypeCommand( PLOT_DASH_TYPE linetype )
} }
} }
static double dpoint_dist( DPOINT a, DPOINT b ) static double dpoint_dist( DPOINT a, DPOINT b )
{ {
DPOINT diff = a - b; DPOINT diff = a - b;

View File

@ -7,7 +7,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2012 Lorenzo Marcantonio, l.marcantonio@logossrl.com * Copyright (C) 1992-2012 Lorenzo Marcantonio, l.marcantonio@logossrl.com
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -123,7 +123,7 @@ bool PDF_PLOTTER::OpenFile( const wxString& aFullFilename )
void PDF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, void PDF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) double aScale, bool aMirror )
{ {
m_plotMirror = aMirror; m_plotMirror = aMirror;
m_plotOffset = aOffset; m_plotOffset = aOffset;
@ -162,8 +162,7 @@ void PDF_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData )
void PDF_PLOTTER::emitSetRGBColor( double r, double g, double b ) void PDF_PLOTTER::emitSetRGBColor( double r, double g, double b )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
fprintf( workFile, "%g %g %g rg %g %g %g RG\n", fprintf( workFile, "%g %g %g rg %g %g %g RG\n", r, g, b, r, g, b );
r, g, b, r, g, b );
} }
@ -257,7 +256,7 @@ void PDF_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE aFill, int
void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_TYPE fill, int width )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
@ -282,6 +281,7 @@ void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) ); start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) );
DPOINT pos_dev = userToDeviceCoordinates( start ); DPOINT pos_dev = userToDeviceCoordinates( start );
fprintf( workFile, "%g %g m ", pos_dev.x, pos_dev.y ); fprintf( workFile, "%g %g m ", pos_dev.x, pos_dev.y );
for( int ii = StAngle + delta; ii < EndAngle; ii += delta ) for( int ii = StAngle + delta; ii < EndAngle; ii += delta )
{ {
end.x = centre.x + KiROUND( cosdecideg( radius, -ii ) ); end.x = centre.x + KiROUND( cosdecideg( radius, -ii ) );
@ -310,7 +310,7 @@ void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
void PDF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, void PDF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_TYPE aFill, int aWidth, void * aData ) FILL_TYPE aFill, int aWidth, void* aData )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
@ -363,19 +363,16 @@ void PDF_PLOTTER::PenTo( const wxPoint& pos, char plume )
} }
void PDF_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos, void PDF_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos, double aScaleFactor )
double aScaleFactor )
{ {
wxASSERT( workFile ); wxASSERT( workFile );
wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() ); wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() );
// Requested size (in IUs) // Requested size (in IUs)
DPOINT drawsize( aScaleFactor * pix_size.x, DPOINT drawsize( aScaleFactor * pix_size.x, aScaleFactor * pix_size.y );
aScaleFactor * pix_size.y );
// calculate the bitmap start position // calculate the bitmap start position
wxPoint start( aPos.x - drawsize.x / 2, wxPoint start( aPos.x - drawsize.x / 2, aPos.y + drawsize.y / 2);
aPos.y + drawsize.y / 2);
DPOINT dev_start = userToDeviceCoordinates( start ); DPOINT dev_start = userToDeviceCoordinates( start );
@ -390,9 +387,9 @@ void PDF_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos,
4) profit 4) profit
*/ */
fprintf( workFile, "q %g 0 0 %g %g %g cm\n", // Step 1 fprintf( workFile, "q %g 0 0 %g %g %g cm\n", // Step 1
userToDeviceSize( drawsize.x ), userToDeviceSize( drawsize.x ),
userToDeviceSize( drawsize.y ), userToDeviceSize( drawsize.y ),
dev_start.x, dev_start.y ); dev_start.x, dev_start.y );
/* An inline image is a cross between a dictionary and a stream. /* An inline image is a cross between a dictionary and a stream.
A real ugly construct (compared with the elegance of the PDF A real ugly construct (compared with the elegance of the PDF
@ -756,8 +753,7 @@ bool PDF_PLOTTER::EndPlot()
int infoDictHandle = startPdfObject(); int infoDictHandle = startPdfObject();
char date_buf[250]; char date_buf[250];
time_t ltime = time( NULL ); time_t ltime = time( NULL );
strftime( date_buf, 250, "D:%Y%m%d%H%M%S", strftime( date_buf, 250, "D:%Y%m%d%H%M%S", localtime( &ltime ) );
localtime( &ltime ) );
if( m_title.IsEmpty() ) if( m_title.IsEmpty() )
{ {
@ -822,7 +818,7 @@ bool PDF_PLOTTER::EndPlot()
void PDF_PLOTTER::Text( const wxPoint& aPos, void PDF_PLOTTER::Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -46,6 +46,7 @@ extern const double hvbo_widths[256];
const double PSLIKE_PLOTTER::postscriptTextAscent = 0.718; const double PSLIKE_PLOTTER::postscriptTextAscent = 0.718;
// return a id used to select a ps macro (see StartPlot() ) from a FILL_TYPE // return a id used to select a ps macro (see StartPlot() ) from a FILL_TYPE
// fill mode, for arc, rect, circle and poly draw primitives // fill mode, for arc, rect, circle and poly draw primitives
static int getFillId( FILL_TYPE aFill ) static int getFillId( FILL_TYPE aFill )
@ -60,9 +61,7 @@ static int getFillId( FILL_TYPE aFill )
} }
// Common routines for PostScript-like plotting engines void PSLIKE_PLOTTER::SetColor( const COLOR4D& color )
void PSLIKE_PLOTTER::SetColor( COLOR4D color )
{ {
if( m_colorMode ) if( m_colorMode )
{ {
@ -112,7 +111,7 @@ void PSLIKE_PLOTTER::FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize,
if( aTraceMode == FILLED ) if( aTraceMode == FILLED )
ThickSegment( wxPoint( aPadPos.x + x0, aPadPos.y + y0 ), ThickSegment( wxPoint( aPadPos.x + x0, aPadPos.y + y0 ),
wxPoint( aPadPos.x + x1, aPadPos.y + y1 ), size.x, aTraceMode, NULL ); wxPoint( aPadPos.x + x1, aPadPos.y + y1 ), size.x, aTraceMode, nullptr );
else else
sketchOval( aPadPos, size, aPadOrient, -1 ); sketchOval( aPadPos, size, aPadOrient, -1 );
} }
@ -122,7 +121,9 @@ void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
OUTLINE_MODE aTraceMode, void* aData ) OUTLINE_MODE aTraceMode, void* aData )
{ {
if( aTraceMode == FILLED ) if( aTraceMode == FILLED )
{
Circle( aPadPos, aDiameter, FILL_TYPE::FILLED_SHAPE, 0 ); Circle( aPadPos, aDiameter, FILL_TYPE::FILLED_SHAPE, 0 );
}
else // Plot a ring: else // Plot a ring:
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
@ -195,7 +196,9 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
wxSize size( aSize ); wxSize size( aSize );
if( aTraceMode == FILLED ) if( aTraceMode == FILLED )
{
SetCurrentLineWidth( 0 ); SetCurrentLineWidth( 0 );
}
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
@ -231,7 +234,9 @@ void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize
wxSize size( aSize ); wxSize size( aSize );
if( aTraceMode == FILLED ) if( aTraceMode == FILLED )
{
SetCurrentLineWidth( 0 ); SetCurrentLineWidth( 0 );
}
else else
{ {
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
@ -304,9 +309,8 @@ void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCor
} }
void PSLIKE_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, void PSLIKE_PLOTTER::FlashRegularPolygon( const wxPoint& aShapePos, int aRadius, int aCornerCount,
int aRadius, int aCornerCount, double aOrient, OUTLINE_MODE aTraceMode, void* aData )
double aOrient, OUTLINE_MODE aTraceMode, void* aData )
{ {
// Do nothing // Do nothing
wxASSERT( 0 ); wxASSERT( 0 );
@ -352,12 +356,6 @@ std::string PSLIKE_PLOTTER::encodeStringForPlotter( const wxString& aUnicode )
} }
/**
* Sister function for the GraphicTextWidth in drawtxt.cpp
* Does the same processing (i.e. calculates a text string width) but
* using postscript metrics for the Helvetica font (optionally used for
* PS and PDF plotting
*/
int PSLIKE_PLOTTER::returnPostscriptTextWidth( const wxString& aText, int aXSize, int PSLIKE_PLOTTER::returnPostscriptTextWidth( const wxString& aText, int aXSize,
bool aItalic, bool aBold ) bool aItalic, bool aBold )
{ {
@ -381,12 +379,6 @@ int PSLIKE_PLOTTER::returnPostscriptTextWidth( const wxString& aText, int aXSize
} }
/**
* Computes the x coordinates for the overlining in a string of text.
* Fills the passed vector with couples of (start, stop) values to be
* used in the text coordinate system (use computeTextParameters to
* obtain the parameters to establish such a system)
*/
void PSLIKE_PLOTTER::postscriptOverlinePositions( const wxString& aText, int aXSize, void PSLIKE_PLOTTER::postscriptOverlinePositions( const wxString& aText, int aXSize,
bool aItalic, bool aBold, bool aItalic, bool aBold,
std::vector<int> *pos_pairs ) std::vector<int> *pos_pairs )
@ -417,8 +409,9 @@ void PSLIKE_PLOTTER::postscriptOverlinePositions( const wxString& aText, int aXS
pos_pairs->push_back( KiROUND( aXSize * tally / postscriptTextAscent ) ); pos_pairs->push_back( KiROUND( aXSize * tally / postscriptTextAscent ) );
} }
void PS_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, void PS_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) double aScale, bool aMirror )
{ {
wxASSERT( !m_outputFile ); wxASSERT( !m_outputFile );
m_plotMirror = aMirror; m_plotMirror = aMirror;
@ -433,12 +426,6 @@ void PS_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
} }
/** This is the core for postscript/PDF text alignment
* It computes the transformation matrix to generate a user space
* system aligned with the text. Even the PS uses the concat
* operator to simplify PDF generation (concat is everything PDF
* has to modify the CTM. Lots of parameters, both in and out.
*/
void PSLIKE_PLOTTER::computeTextParameters( const wxPoint& aPos, void PSLIKE_PLOTTER::computeTextParameters( const wxPoint& aPos,
const wxString& aText, const wxString& aText,
int aOrient, int aOrient,
@ -530,8 +517,6 @@ void PSLIKE_PLOTTER::computeTextParameters( const wxPoint& aPos,
} }
/* Set the current line width (in IUs) for the next plot
*/
void PS_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData ) void PS_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData )
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -561,9 +546,6 @@ void PS_PLOTTER::emitSetRGBColor( double r, double g, double b )
} }
/**
* PostScript supports dashed lines
*/
void PS_PLOTTER::SetDash( PLOT_DASH_TYPE dashed ) void PS_PLOTTER::SetDash( PLOT_DASH_TYPE dashed )
{ {
switch( dashed ) switch( dashed )
@ -668,11 +650,7 @@ void PS_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList,
} }
/** void PS_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor )
* PostScript-likes at the moment are the only plot engines supporting bitmaps...
*/
void PS_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos,
double aScaleFactor )
{ {
wxSize pix_size; // size of the bitmap in pixels wxSize pix_size; // size of the bitmap in pixels
pix_size.x = aImage.GetWidth(); pix_size.x = aImage.GetWidth();
@ -712,6 +690,7 @@ void PS_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos,
fputs( "false 3 colorimage\n", m_outputFile ); fputs( "false 3 colorimage\n", m_outputFile );
else else
fputs( "image\n", m_outputFile ); fputs( "image\n", m_outputFile );
// Single data source, 3 colors, Output RGB data (hexadecimal) // Single data source, 3 colors, Output RGB data (hexadecimal)
// (or the same downscaled to gray) // (or the same downscaled to gray)
int jj = 0; int jj = 0;
@ -810,19 +789,6 @@ void PS_PLOTTER::PenTo( const wxPoint& pos, char plume )
} }
/**
* The code within this function (and the CloseFilePS function)
* creates postscript files whose contents comply with Adobe's
* Document Structuring Convention, as documented by assorted
* details described within the following URLs:
*
* http://en.wikipedia.org/wiki/Document_Structuring_Conventions
* http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf
*
*
* BBox is the boundary box (position and size of the "client rectangle"
* for drawings (page - margins) in mils (0.001 inch)
*/
bool PS_PLOTTER::StartPlot() bool PS_PLOTTER::StartPlot()
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -878,10 +844,10 @@ bool PS_PLOTTER::StartPlot()
"/KicadFont-Oblique /Helvetica-Oblique reencodefont definefont pop\n", "/KicadFont-Oblique /Helvetica-Oblique reencodefont definefont pop\n",
"/KicadFont-BoldOblique /Helvetica-BoldOblique reencodefont definefont pop\n", "/KicadFont-BoldOblique /Helvetica-BoldOblique reencodefont definefont pop\n",
"%%EndProlog\n", "%%EndProlog\n",
NULL nullptr
}; };
time_t time1970 = time( NULL ); time_t time1970 = time( nullptr );
fputs( "%!PS-Adobe-3.0\n", m_outputFile ); // Print header fputs( "%!PS-Adobe-3.0\n", m_outputFile ); // Print header
@ -947,7 +913,7 @@ bool PS_PLOTTER::StartPlot()
// Now specify various other details. // Now specify various other details.
for( int ii = 0; PSMacro[ii] != NULL; ii++ ) for( int ii = 0; PSMacro[ii] != nullptr; ii++ )
{ {
fputs( PSMacro[ii], m_outputFile ); fputs( PSMacro[ii], m_outputFile );
} }
@ -987,7 +953,7 @@ bool PS_PLOTTER::EndPlot()
"grestore\n" "grestore\n"
"%%EOF\n", m_outputFile ); "%%EOF\n", m_outputFile );
fclose( m_outputFile ); fclose( m_outputFile );
m_outputFile = NULL; m_outputFile = nullptr;
return true; return true;
} }
@ -995,7 +961,7 @@ bool PS_PLOTTER::EndPlot()
void PS_PLOTTER::Text( const wxPoint& aPos, void PS_PLOTTER::Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -1061,6 +1027,7 @@ const double hv_widths[256] = {
0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500 0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500
}; };
/** /**
* Character widths for Helvetica-Bold * Character widths for Helvetica-Bold
*/ */
@ -1099,6 +1066,7 @@ const double hvb_widths[256] = {
0.611, 0.611, 0.611, 0.611, 0.611, 0.556, 0.611, 0.556 0.611, 0.611, 0.611, 0.611, 0.611, 0.556, 0.611, 0.556
}; };
/** /**
* Character widths for Helvetica-Oblique * Character widths for Helvetica-Oblique
*/ */
@ -1137,6 +1105,7 @@ const double hvo_widths[256] = {
0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500 0.611, 0.556, 0.556, 0.556, 0.556, 0.500, 0.556, 0.500
}; };
/** /**
* Character widths for Helvetica-BoldOblique * Character widths for Helvetica-BoldOblique
*/ */

View File

@ -7,7 +7,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -106,8 +106,7 @@
/** /**
* Function XmlEsc * Translates '<' to "&lt;", '>' to "&gt;" and so on, according to the spec:
* translates '<' to "&lt;", '>' to "&gt;" and so on, according to the spec:
* http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping * http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping
* May be moved to a library if needed generally, but not expecting that. * May be moved to a library if needed generally, but not expecting that.
*/ */
@ -171,7 +170,7 @@ SVG_PLOTTER::SVG_PLOTTER()
m_brush_rgb_color = 0; // current color value (black) m_brush_rgb_color = 0; // current color value (black)
m_dashed = PLOT_DASH_TYPE::SOLID; m_dashed = PLOT_DASH_TYPE::SOLID;
m_useInch = true; // decimils is the default m_useInch = true; // decimils is the default
m_precision = 4; // because there where used before it was changable m_precision = 4; // because there where used before it was changeable
} }
@ -190,7 +189,7 @@ void SVG_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
m_paperSize.y *= 10.0 * aIusPerDecimil; m_paperSize.y *= 10.0 * aIusPerDecimil;
// set iuPerDeviceUnit, in 0.1mils ( 2.54um ) // set iuPerDeviceUnit, in 0.1mils ( 2.54um )
// this was used before the format was changable, so we set is as default // this was used before the format was changeable, so we set is as default
SetSvgCoordinatesFormat( 4, true ); SetSvgCoordinatesFormat( 4, true );
} }
@ -208,7 +207,7 @@ void SVG_PLOTTER::SetSvgCoordinatesFormat( unsigned aResolution, bool aUseInches
} }
void SVG_PLOTTER::SetColor( COLOR4D color ) void SVG_PLOTTER::SetColor( const COLOR4D& color )
{ {
PSLIKE_PLOTTER::SetColor( color ); PSLIKE_PLOTTER::SetColor( color );
@ -273,7 +272,8 @@ void SVG_PLOTTER::setSVGPlotStyle( bool aIsGroup, const std::string& aExtraStyle
fprintf( m_outputFile, "stroke-dasharray:%f,%f;", GetDotMarkLenIU(), GetDashGapLenIU() ); fprintf( m_outputFile, "stroke-dasharray:%f,%f;", GetDotMarkLenIU(), GetDashGapLenIU() );
break; break;
case PLOT_DASH_TYPE::DASHDOT: case PLOT_DASH_TYPE::DASHDOT:
fprintf( m_outputFile, "stroke-dasharray:%f,%f,%f,%f;", GetDashMarkLenIU(), GetDashGapLenIU(), fprintf( m_outputFile, "stroke-dasharray:%f,%f,%f,%f;",
GetDashMarkLenIU(), GetDashGapLenIU(),
GetDotMarkLenIU(), GetDashGapLenIU() ); GetDotMarkLenIU(), GetDashGapLenIU() );
break; break;
case PLOT_DASH_TYPE::DEFAULT: case PLOT_DASH_TYPE::DEFAULT:
@ -299,8 +299,7 @@ void SVG_PLOTTER::setSVGPlotStyle( bool aIsGroup, const std::string& aExtraStyle
fputs( "\n", m_outputFile ); fputs( "\n", m_outputFile );
} }
/* Set the current line width (in IUs) for the next plot
*/
void SVG_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData ) void SVG_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData )
{ {
if( aWidth == DO_NOT_SET_LINE_WIDTH ) if( aWidth == DO_NOT_SET_LINE_WIDTH )
@ -344,9 +343,6 @@ void SVG_PLOTTER::EndBlock( void* aData )
} }
/* initialize m_red, m_green, m_blue ( 0 ... 255)
* from reduced values r, g ,b ( 0.0 to 1.0 )
*/
void SVG_PLOTTER::emitSetRGBColor( double r, double g, double b ) void SVG_PLOTTER::emitSetRGBColor( double r, double g, double b )
{ {
int red = (int) ( 255.0 * r ); int red = (int) ( 255.0 * r );
@ -366,9 +362,6 @@ void SVG_PLOTTER::emitSetRGBColor( double r, double g, double b )
} }
/**
* SVG supports dashed lines
*/
void SVG_PLOTTER::SetDash( PLOT_DASH_TYPE dashed ) void SVG_PLOTTER::SetDash( PLOT_DASH_TYPE dashed )
{ {
if( m_dashed != dashed ) if( m_dashed != dashed )
@ -398,7 +391,7 @@ void SVG_PLOTTER::Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, in
setFillMode( fill ); setFillMode( fill );
SetCurrentLineWidth( width ); SetCurrentLineWidth( width );
// Rectangles having a 0 size value for height or width are just not drawn on Inscape, // Rectangles having a 0 size value for height or width are just not drawn on Inkscape,
// so use a line when happens. // so use a line when happens.
if( rect_dev.GetSize().x == 0.0 || rect_dev.GetSize().y == 0.0 ) // Draw a line if( rect_dev.GetSize().x == 0.0 || rect_dev.GetSize().y == 0.0 ) // Draw a line
{ {
@ -444,7 +437,7 @@ void SVG_PLOTTER::Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, int
void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius, void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int radius,
FILL_TYPE fill, int width ) FILL_TYPE fill, int width )
{ {
/* Draws an arc of a circle, centred on (xc,yc), with starting point /* Draws an arc of a circle, centered on (xc,yc), with starting point
* (x1, y1) and ending at (x2, y2). The current pen is used for the outline * (x1, y1) and ending at (x2, y2). The current pen is used for the outline
* and the current brush for filling the shape. * and the current brush for filling the shape.
* *
@ -523,7 +516,7 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
// end point // end point
if( fill != FILL_TYPE::NO_FILL ) if( fill != FILL_TYPE::NO_FILL )
{ {
// Filled arcs (in eeschema) consist of the pie wedge and a stroke only on the arc // Filled arcs (in Eeschema) consist of the pie wedge and a stroke only on the arc
// This needs to be drawn in two steps. // This needs to be drawn in two steps.
setFillMode( fill ); setFillMode( fill );
SetCurrentLineWidth( 0 ); SetCurrentLineWidth( 0 );
@ -544,8 +537,8 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
void SVG_PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1, void SVG_PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
const wxPoint& aControl2, const wxPoint& aEnd, const wxPoint& aControl2, const wxPoint& aEnd,
int aTolerance, int aLineThickness ) int aTolerance, int aLineThickness )
{ {
#if 1 #if 1
setFillMode( FILL_TYPE::NO_FILL ); setFillMode( FILL_TYPE::NO_FILL );
@ -566,8 +559,8 @@ void SVG_PLOTTER::BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
} }
void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList, FILL_TYPE aFill,
FILL_TYPE aFill, int aWidth, void * aData ) int aWidth, void* aData )
{ {
if( aCornerList.size() <= 1 ) if( aCornerList.size() <= 1 )
return; return;
@ -601,9 +594,11 @@ void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
fprintf( m_outputFile, "%f,%f\n", pos.x, pos.y ); fprintf( m_outputFile, "%f,%f\n", pos.x, pos.y );
} }
// If the cornerlist ends where it begins, then close the poly // If the corner list ends where it begins, then close the poly
if( aCornerList.front() == aCornerList.back() ) if( aCornerList.front() == aCornerList.back() )
{
fprintf( m_outputFile, "Z\" /> \n" ); fprintf( m_outputFile, "Z\" /> \n" );
}
else else
{ {
pos = userToDeviceCoordinates( aCornerList.back() ); pos = userToDeviceCoordinates( aCornerList.back() );
@ -612,23 +607,17 @@ void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
} }
/** void SVG_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor )
* PostScript-likes at the moment are the only plot engines supporting bitmaps...
*/
void SVG_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos,
double aScaleFactor )
{ {
wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() ); wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() );
// Requested size (in IUs) // Requested size (in IUs)
DPOINT drawsize( aScaleFactor * pix_size.x, DPOINT drawsize( aScaleFactor * pix_size.x, aScaleFactor * pix_size.y );
aScaleFactor * pix_size.y );
// calculate the bitmap start position // calculate the bitmap start position
wxPoint start( aPos.x - drawsize.x / 2, wxPoint start( aPos.x - drawsize.x / 2, aPos.y - drawsize.y / 2);
aPos.y - drawsize.y / 2);
// Rectangles having a 0 size value for height or width are just not drawn on Inscape, // Rectangles having a 0 size value for height or width are just not drawn on Inkscape,
// so use a line when happens. // so use a line when happens.
if( drawsize.x == 0.0 || drawsize.y == 0.0 ) // Draw a line if( drawsize.x == 0.0 || drawsize.y == 0.0 ) // Draw a line
{ {
@ -648,8 +637,7 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos,
fprintf( m_outputFile, fprintf( m_outputFile,
"<image x=\"%f\" y=\"%f\" xlink:href=\"data:image/png;base64,", "<image x=\"%f\" y=\"%f\" xlink:href=\"data:image/png;base64,",
userToDeviceSize( start.x ), userToDeviceSize( start.y ) userToDeviceSize( start.x ), userToDeviceSize( start.y ) );
);
for( size_t i = 0; i < encoded.size(); i++ ) for( size_t i = 0; i < encoded.size(); i++ )
{ {
@ -684,7 +672,7 @@ void SVG_PLOTTER::PenTo( const wxPoint& pos, char plume )
{ {
DPOINT pos_dev = userToDeviceCoordinates( pos ); DPOINT pos_dev = userToDeviceCoordinates( pos );
// Ensure we do not use a fill mode when moving tne pen, // Ensure we do not use a fill mode when moving the pen,
// in SVG mode (i;e. we are plotting only basic lines, not a filled area // in SVG mode (i;e. we are plotting only basic lines, not a filled area
if( m_fillMode != FILL_TYPE::NO_FILL ) if( m_fillMode != FILL_TYPE::NO_FILL )
{ {
@ -692,14 +680,12 @@ void SVG_PLOTTER::PenTo( const wxPoint& pos, char plume )
setSVGPlotStyle(); setSVGPlotStyle();
} }
fprintf( m_outputFile, "<path d=\"M%d %d\n", fprintf( m_outputFile, "<path d=\"M%d %d\n", (int) pos_dev.x, (int) pos_dev.y );
(int) pos_dev.x, (int) pos_dev.y );
} }
else if( m_penState != plume || pos != m_penLastpos ) else if( m_penState != plume || pos != m_penLastpos )
{ {
DPOINT pos_dev = userToDeviceCoordinates( pos ); DPOINT pos_dev = userToDeviceCoordinates( pos );
fprintf( m_outputFile, "L%d %d\n", fprintf( m_outputFile, "L%d %d\n", (int) pos_dev.x, (int) pos_dev.y );
(int) pos_dev.x, (int) pos_dev.y );
} }
m_penState = plume; m_penState = plume;
@ -707,10 +693,6 @@ void SVG_PLOTTER::PenTo( const wxPoint& pos, char plume )
} }
/**
* The code within this function
* creates SVG files header
*/
bool SVG_PLOTTER::StartPlot() bool SVG_PLOTTER::StartPlot()
{ {
wxASSERT( m_outputFile ); wxASSERT( m_outputFile );
@ -726,11 +708,11 @@ bool SVG_PLOTTER::StartPlot()
" xmlns=\"http://www.w3.org/2000/svg\"\n", " xmlns=\"http://www.w3.org/2000/svg\"\n",
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n", " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n",
" version=\"1.1\"\n", " version=\"1.1\"\n",
NULL nullptr
}; };
// Write header. // Write header.
for( int ii = 0; header[ii] != NULL; ii++ ) for( int ii = 0; header[ii] != nullptr; ii++ )
{ {
fputs( header[ii], m_outputFile ); fputs( header[ii], m_outputFile );
} }
@ -740,17 +722,18 @@ bool SVG_PLOTTER::StartPlot()
fprintf( m_outputFile, " width=\"%fcm\" height=\"%fcm\" viewBox=\"%d %d %d %d\">\n", fprintf( m_outputFile, " width=\"%fcm\" height=\"%fcm\" viewBox=\"%d %d %d %d\">\n",
(double) m_paperSize.x / m_IUsPerDecimil * 2.54 / 10000, (double) m_paperSize.x / m_IUsPerDecimil * 2.54 / 10000,
(double) m_paperSize.y / m_IUsPerDecimil * 2.54 / 10000, origin.x, origin.y, (double) m_paperSize.y / m_IUsPerDecimil * 2.54 / 10000, origin.x, origin.y,
(int) ( m_paperSize.x * m_iuPerDeviceUnit ), (int) ( m_paperSize.y * m_iuPerDeviceUnit) ); (int) ( m_paperSize.x * m_iuPerDeviceUnit ),
(int) ( m_paperSize.y * m_iuPerDeviceUnit) );
// Write title // Write title
char date_buf[250]; char date_buf[250];
time_t ltime = time( NULL ); time_t ltime = time( nullptr );
strftime( date_buf, 250, "%Y/%m/%d %H:%M:%S", strftime( date_buf, 250, "%Y/%m/%d %H:%M:%S", localtime( &ltime ) );
localtime( &ltime ) );
fprintf( m_outputFile, fprintf( m_outputFile,
"<title>SVG Picture created as %s date %s </title>\n", "<title>SVG Picture created as %s date %s </title>\n",
TO_UTF8( XmlEsc( wxFileName( m_filename ).GetFullName() ) ), date_buf ); TO_UTF8( XmlEsc( wxFileName( m_filename ).GetFullName() ) ), date_buf );
// End of header // End of header
fprintf( m_outputFile, " <desc>Picture generated by %s </desc>\n", fprintf( m_outputFile, " <desc>Picture generated by %s </desc>\n",
TO_UTF8( XmlEsc( m_creator ) ) ); TO_UTF8( XmlEsc( m_creator ) ) );
@ -772,14 +755,14 @@ bool SVG_PLOTTER::EndPlot()
{ {
fputs( "</g> \n</svg>\n", m_outputFile ); fputs( "</g> \n</svg>\n", m_outputFile );
fclose( m_outputFile ); fclose( m_outputFile );
m_outputFile = NULL; m_outputFile = nullptr;
return true; return true;
} }
void SVG_PLOTTER::Text( const wxPoint& aPos, void SVG_PLOTTER::Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -829,7 +812,7 @@ void SVG_PLOTTER::Text( const wxPoint& aPos,
wxSize text_size; wxSize text_size;
// aSize.x or aSize.y is < 0 for mirrored texts. // aSize.x or aSize.y is < 0 for mirrored texts.
// The actual text size value is the absolue value // The actual text size value is the absolute value
text_size.x = std::abs( GraphicTextWidth( aText, aSize, aItalic, aWidth ) ); text_size.x = std::abs( GraphicTextWidth( aText, aSize, aItalic, aWidth ) );
text_size.y = std::abs( aSize.x * 4/3 ); // Hershey font height to em size conversion text_size.y = std::abs( aSize.x * 4/3 ); // Hershey font height to em size conversion
DPOINT anchor_pos_dev = userToDeviceCoordinates( aPos ); DPOINT anchor_pos_dev = userToDeviceCoordinates( aPos );

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software: you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
@ -61,37 +61,80 @@ public:
m_textAsLines = ( mode != PLOT_TEXT_MODE::NATIVE ); m_textAsLines = ( mode != PLOT_TEXT_MODE::NATIVE );
} }
/**
* Opens the DXF plot with a skeleton header.
*/
virtual bool StartPlot() override; virtual bool StartPlot() override;
virtual bool EndPlot() override; virtual bool EndPlot() override;
// For now we don't use 'thick' primitives, so no line width // For now we don't use 'thick' primitives, so no line width
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override
{ {
m_currentPenWidth = 0; m_currentPenWidth = 0;
} }
virtual void SetDash( PLOT_DASH_TYPE dashed ) override; virtual void SetDash( PLOT_DASH_TYPE dashed ) override;
virtual void SetColor( COLOR4D color ) override; /**
* The DXF exporter handles 'colors' as layers...
*/
virtual void SetColor( const COLOR4D& color ) override;
/**
* Set the scale/position for the DXF plot.
*
* The DXF engine doesn't support line widths and mirroring. The output
* coordinate system is in the first quadrant (in mm).
*/
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
/**
* DXF rectangle: fill not supported.
*/
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
/**
* DXF circle: full functionality; it even does 'fills' drawing a
* circle with a dual-arc polyline wide as the radius.
*
* I could use this trick to do other filled primitives.
*/
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = NULL ) override; /**
* DXF polygon: doesn't fill it but at least it close the filled ones
* DXF does not know thick outline.
*
* It does not know thick segments, therefore filled polygons with thick outline
* are converted to inflated polygon by aWidth/2.
*/
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
OUTLINE_MODE tracemode, void* aData ) override; OUTLINE_MODE tracemode, void* aData ) override;
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
/**
* DXF round pad: always done in sketch mode; it could be filled but it isn't
* pretty if other kinds of pad aren't...
*/
virtual void FlashPadCircle( const wxPoint& pos, int diametre, virtual void FlashPadCircle( const wxPoint& pos, int diametre,
OUTLINE_MODE trace_mode, void* aData ) override; OUTLINE_MODE trace_mode, void* aData ) override;
/**
* DXF oval pad: always done in sketch mode.
*/
virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient, virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient,
OUTLINE_MODE trace_mode, void* aData ) override; OUTLINE_MODE trace_mode, void* aData ) override;
/**
* DXF rectangular pad: always done in sketch mode.
*/
virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, virtual void FlashPadRect( const wxPoint& pos, const wxSize& size,
double orient, OUTLINE_MODE trace_mode, void* aData ) override; double orient, OUTLINE_MODE trace_mode, void* aData ) override;
virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
@ -100,13 +143,17 @@ public:
virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, double aOrient, virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, double aOrient,
SHAPE_POLY_SET* aPolygons, SHAPE_POLY_SET* aPolygons,
OUTLINE_MODE aTraceMode, void* aData ) override; OUTLINE_MODE aTraceMode, void* aData ) override;
/**
* DXF trapezoidal pad: only sketch mode is supported.
*/
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) override; double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) override;
virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount, virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount,
double aOrient, OUTLINE_MODE aTraceMode, void* aData ) override; double aOrient, OUTLINE_MODE aTraceMode, void* aData ) override;
virtual void Text( const wxPoint& aPos, virtual void Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -116,7 +163,7 @@ public:
bool aItalic, bool aItalic,
bool aBold, bool aBold,
bool aMultilineAllowed = false, bool aMultilineAllowed = false,
void* aData = NULL ) override; void* aData = nullptr ) override;
/** /**

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software: you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
@ -51,23 +51,22 @@ public:
} }
/** /**
* Function StartPlot * Write GERBER header to file initialize global variable g_Plot_PlotOutputFile.
* Write GERBER header to file
* initialize global variable g_Plot_PlotOutputFile
*/ */
virtual bool StartPlot() override; virtual bool StartPlot() override;
virtual bool EndPlot() override; virtual bool EndPlot() override;
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override; virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override;
// RS274X has no dashing, nor colours // RS274X has no dashing, nor colors
virtual void SetDash( PLOT_DASH_TYPE dashed ) override virtual void SetDash( PLOT_DASH_TYPE dashed ) override
{ {
} }
virtual void SetColor( COLOR4D color ) override {} virtual void SetColor( const COLOR4D& color ) override {}
// Currently, aScale and aMirror are not used in gerber plotter // Currently, aScale and aMirror are not used in gerber plotter
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
// Basic plot primitives // Basic plot primitives
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
@ -96,17 +95,16 @@ public:
* Gerber polygon: they can (and *should*) be filled with the * Gerber polygon: they can (and *should*) be filled with the
* appropriate G36/G37 sequence * appropriate G36/G37 sequence
*/ */
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
void* aData = nullptr ) override;
virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = NULL ) override; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
virtual void Text( const wxPoint& aPos, virtual void Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -116,7 +114,7 @@ public:
bool aItalic, bool aItalic,
bool aBold, bool aBold,
bool aMultilineAllowed = false, bool aMultilineAllowed = false,
void* aData = NULL ) override; void* aData = nullptr ) override;
/** /**
* Filled circular flashes are stored as apertures * Filled circular flashes are stored as apertures
@ -144,146 +142,154 @@ public:
double aOrient, OUTLINE_MODE aTraceMode, void* aData ) override; double aOrient, OUTLINE_MODE aTraceMode, void* aData ) override;
/** /**
* flash a chamfered round rect pad. * Flash a chamfered round rect pad.
* @param aShapePos = position of the pad shape *
* @param aPadSize = size of the rectangle * @param aShapePos is the position of the pad shape.
* @param aCornerRadius = radius of rounded corners * @param aPadSize is the size of the rectangle.
* @param aChamferRatio = chamfer value (ratio < 0.5 between smallest size and chamfer) * @param aCornerRadius is the radius of rounded corners.
* @param aChamferPositions = identifier of the corners to chamfer: * @param aChamferRatio is the chamfer value (ratio < 0.5 between smallest size and chamfer).
* @param aChamferPositions is the identifier of the corners to chamfer:
* 0 = no chamfer * 0 = no chamfer
* 1 = TOP_LEFT * 1 = TOP_LEFT
* 2 = TOP_RIGHT * 2 = TOP_RIGHT
* 4 = BOTTOM_LEFT * 4 = BOTTOM_LEFT
* 8 = BOTTOM_RIGHT * 8 = BOTTOM_RIGHT
* @param aPadOrient = rotation in 0.1 degrees of the shape * @param aPadOrient is the rotation in 0.1 degrees of the shape.
* @param aPlotMode = FILLED or SKETCH * @param aPlotMode is the drawing mode, FILLED or SKETCH.
* @param aData = a reference to Gerber attributes descr * @param aData is the a reference to Gerber attributes descr.
*/ */
void FlashPadChamferRoundRect( const wxPoint& aShapePos, const wxSize& aPadSize, void FlashPadChamferRoundRect( const wxPoint& aShapePos, const wxSize& aPadSize,
int aCornerRadius, double aChamferRatio, int aCornerRadius, double aChamferRatio,
int aChamferPositions, int aChamferPositions, double aPadOrient,
double aPadOrient, OUTLINE_MODE aPlotMode, void* aData ); OUTLINE_MODE aPlotMode, void* aData );
/** /**
* Plot a Gerber region: similar to PlotPoly but plot only filled polygon, * Plot a Gerber region: similar to PlotPoly but plot only filled polygon,
* and add the TA.AperFunction if aData contains this attribute, and clear it * and add the TA.AperFunction if aData contains this attribute, and clear it
* after plotting * after plotting.
*/ */
void PlotGerberRegion( const std::vector< wxPoint >& aCornerList, void PlotGerberRegion( const std::vector< wxPoint >& aCornerList, void* aData = nullptr );
void * aData = NULL );
void PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aData = nullptr );
void * aData = NULL );
/** /**
* Change the plot polarity and begin a new layer * Change the plot polarity and begin a new layer.
* Used to 'scratch off' silk screen away from solder mask *
* Used to 'scratch off' silk screen away from solder mask.
*/ */
virtual void SetLayerPolarity( bool aPositive ) override; virtual void SetLayerPolarity( bool aPositive ) override;
/** /**
* Function SetGerberCoordinatesFormat * Selection of Gerber units and resolution (number of digits in mantissa).
* selection of Gerber units and resolution (number of digits in mantissa)
* @param aResolution = number of digits in mantissa of coordinate
* use 5 or 6 for mm and 6 or 7 for inches
* do not use value > 6 (mm) or > 7 (in) to avoid overflow
* @param aUseInches = true to use inches, false to use mm (default)
* *
* Should be called only after SetViewport() is called * Should be called only after SetViewport() is called.
*
* @param aResolution is the number of digits in mantissa of coordinate
* use 5 or 6 for mm and 6 or 7 for inches
* do not use value > 6 (mm) or > 7 (in) to avoid overflow.
* @param aUseInches use true to use inches, false to use mm (default).
*/ */
virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false ) override; virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false ) override;
void UseX2format( bool aEnable ) { m_useX2format = aEnable; } void UseX2format( bool aEnable ) { m_useX2format = aEnable; }
void UseX2NetAttributes( bool aEnable ) { m_useNetAttributes = aEnable; } void UseX2NetAttributes( bool aEnable ) { m_useNetAttributes = aEnable; }
/** Disable Aperture Macro (AM) command, only for broken Gerber Readers /**
* Regions will be used instead of AM shapes to draw complex shapes * Disable Aperture Macro (AM) command, only for broken Gerber Readers.
* @param aDisable = true to disable Aperture Macro (AM) command. *
* Regions will be used instead of AM shapes to draw complex shapes.
*
* @param aDisable use true to disable Aperture Macro (AM) command.
*/ */
void DisableApertMacros( bool aDisable ) { m_gerberDisableApertMacros = aDisable; } void DisableApertMacros( bool aDisable ) { m_gerberDisableApertMacros = aDisable; }
/** /**
* calling this function allows one to define the beginning of a group * Calling this function allows one to define the beginning of a group
* of drawing items (used in X2 format with netlist attributes) * of drawing items (used in X2 format with netlist attributes).
* @param aData can define any parameter *
* @param aData can define any parameter.
*/ */
virtual void StartBlock( void* aData ) override; virtual void StartBlock( void* aData ) override;
/** /**
* calling this function allows one to define the end of a group of drawing * Define the end of a group of drawing items the group is started by StartBlock().
* items the group is started by StartBlock() *
* (used in X2 format with netlist attributes) * Used in X2 format with netlist attributes.
*
* @param aData can define any parameter * @param aData can define any parameter
*/ */
virtual void EndBlock( void* aData ) override; virtual void EndBlock( void* aData ) override;
/** Remove (clear) all attributes from object attributes dictionary (TO. and TA commands) /**
* similar to clearNetAttribute(), this is an unconditional reset of TO. and TA. attributes * Remove (clear) all attributes from object attributes dictionary (TO. and TA commands)
* similar to clearNetAttribute(), this is an unconditional reset of TO. and TA. attributes.
*/ */
void ClearAllAttributes(); void ClearAllAttributes();
/** /**
* @return a index to the aperture in aperture list which meets the size and type of tool * @param aSize is the size of tool.
* if the aperture does not exist, it is created and entered in aperture list * @param aRadius is the radius used for some shapes tool (oval, roundrect macros).
* @param aSize = the size of tool * @param aRotDegree is the rotation of tool (primitives round, oval rect accept only 0.0).
* @param aRadius = the radius used for some shapes tool (oval, roundrect macros) * @param aType is the type ( shape ) of tool.
* @param aRotDegree = the rotation of tool (primitives round, oval rect accept only 0.0) * @param aApertureAttribute is an aperture attribute of the tool (a tool can have only one
* @param aType = the type ( shape ) of tool * attribute) 0 = no specific attribute.
* @param aApertureAttribute = an aperture attribute of the tool (a tool can have only one attribute) * @return an index to the aperture in aperture list which meets the size and type of tool
* 0 = no specific attribute * if the aperture does not exist, it is created and entered in aperture list.
*/ */
int GetOrCreateAperture( const wxSize& aSize, int aRadius, double aRotDegree, int GetOrCreateAperture( const wxSize& aSize, int aRadius, double aRotDegree,
APERTURE::APERTURE_TYPE aType, int aApertureAttribute ); APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
/** /**
* @return a index to the aperture in aperture list which meets the data and type of tool * @param aCorners is the corner list.
* if the aperture does not exist, it is created and entered in aperture list * @param aRotDegree is the rotation of tool.
* @param aCorners = the corner list * @param aType is the type ( shape ) of tool that can manage a list of corners (polygon).
* @param aRotDegree = the rotation of tool * @param aApertureAttribute is an aperture attribute of the tool (a tool can have only one
* @param aType = the type ( shape ) of tool that can manage a list of corners (polygon) * attribute) 0 = no specific attribute.
* @param aApertureAttribute = an aperture attribute of the tool (a tool can have only one attribute) * @return an index to the aperture in aperture list which meets the data and type of tool
* 0 = no specific attribute * if the aperture does not exist, it is created and entered in aperture list.
*/ */
int GetOrCreateAperture( const std::vector<wxPoint>& aCorners, double aRotDegree, int GetOrCreateAperture( const std::vector<wxPoint>& aCorners, double aRotDegree,
APERTURE::APERTURE_TYPE aType, int aApertureAttribute ); APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
protected: protected:
/** Plot a round rect (a round rect shape in fact) as a Gerber region /**
* using lines and arcs for corners * Plot a round rect (a round rect shape in fact) as a Gerber region using lines and arcs
* @param aRectCenter is the center of the rectangle * for corners.
* @param aSize is the size of the rectangle *
* @param aCornerRadius is the radius of the corners * @note Only the G36 ... G37 region is created.
* @param aOrient is the rotation of the rectangle *
* Note: only the G36 ... G37 region is created. * @param aRectCenter is the center of the rectangle.
* @param aSize is the size of the rectangle.
* @param aCornerRadius is the radius of the corners.
* @param aOrient is the rotation of the rectangle.
*/ */
void plotRoundRectAsRegion( const wxPoint& aRectCenter, const wxSize& aSize, void plotRoundRectAsRegion( const wxPoint& aRectCenter, const wxSize& aSize,
int aCornerRadius, double aOrient ); int aCornerRadius, double aOrient );
/** /**
* Plot a Gerber arc. * Plot a Gerber arc.
* if aPlotInRegion = true, the current pen position will not be *
* initialized to the arc start position, and therefore the arc can be used * If aPlotInRegion = true, the current pen position will not be initialized to the arc
* to define a region outline item * start position, and therefore the arc can be used to define a region outline item
* a line will be created from current ^position to arc start point * a line will be created from current position to arc start point. If aPlotInRegion
* if aPlotInRegion = false, the current pen position will be initialized * = false, the current pen position will be initialized to the arc start position, to
* to the arc start position, to plot an usual arc item * plot an usual arc item. The line thickness is not initialized in plotArc, and must
* The line thickness is not initialized in plotArc, and must be initialized * be initialized before calling it if needed.
* before calling it if needed.
*/ */
void plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle, void plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
int aRadius, bool aPlotInRegion ); int aRadius, bool aPlotInRegion );
void plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion ); void plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion );
/** /**
* Pick an existing aperture or create a new one, matching the * Pick an existing aperture or create a new one, matching the size, type and attributes.
* size, type and attributes. *
* write the DCode selection on gerber file * Write the DCode selection on gerber file.
*/ */
void selectAperture( const wxSize& aSize, int aRadius, double aRotDegree, void selectAperture( const wxSize& aSize, int aRadius, double aRotDegree,
APERTURE::APERTURE_TYPE aType, APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
int aApertureAttribute );
/** /**
* Pick an existing aperture or create a new one, matching the * Pick an existing aperture or create a new one, matching the aDiameter, aPolygonRotation,
* aDiameter, aPolygonRotation, type and attributes. * type and attributes.
*
* It apply only to apertures with type = AT_REGULAR_POLY3 to AT_REGULAR_POLY12 * It apply only to apertures with type = AT_REGULAR_POLY3 to AT_REGULAR_POLY12
* write the DCode selection on gerber file * write the DCode selection on gerber file
*/ */
@ -291,35 +297,39 @@ protected:
APERTURE::APERTURE_TYPE aType, int aApertureAttribute ); APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
/** /**
* Pick an existing aperture or create a new one, matching the * Pick an existing aperture or create a new one, matching the corner list, aRotDegree,
* corner list, aRotDegree, type and attributes. * type and attributes.
* It apply only to apertures managing a polygon that differs from AT_REGULAR_POLY3 *
* to AT_REGULAR_POLY12 (for instance APER_MACRO_TRAPEZOID ) * It only applies to apertures managing a polygon that differs from AT_REGULAR_POLY3
* write the DCode selection on gerber file * to AT_REGULAR_POLY12 (for instance APER_MACRO_TRAPEZOID ) write the DCode selection
* on gerber file.
*/ */
void selectAperture( int aDiameter, double aRotDegree, void selectAperture( int aDiameter, double aRotDegree,
APERTURE::APERTURE_TYPE aType, int aApertureAttribute ); APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
/** /**
* Emit a D-Code record, using proper conversions * Emit a D-Code record, using proper conversions to format a leading zero omitted gerber
* to format a leading zero omitted gerber coordinate * coordinate.
* (for n decimal positions, see header generation in start_plot *
* For n decimal positions, see header generation in start_plot.
*/ */
void emitDcode( const DPOINT& pt, int dcode ); void emitDcode( const DPOINT& pt, int dcode );
/** /**
* print a Gerber net attribute object record. * Print a Gerber net attribute object record.
* In a gerber file, a net attribute is owned by a graphic object *
* formatNetAttribute must be called before creating the object * In a gerber file, a net attribute is owned by a graphic object formatNetAttribute must
* be called before creating the object. The generated string depends on the type of
* netlist info.
*
* @param aData contains the data to format. * @param aData contains the data to format.
* the generated string depends on the type of netlist info
*/ */
void formatNetAttribute( GBR_NETLIST_METADATA* aData ); void formatNetAttribute( GBR_NETLIST_METADATA* aData );
/** /**
* clear a Gerber net attribute record (clear object attribute dictionary) * Clear a Gerber net attribute record (clear object attribute dictionary)
* and output the clear object attribute dictionary command to gerber file * and output the clear object attribute dictionary command to gerber file
* has effect only if a net attribute is stored in m_objectAttributesDictionary * has effect only if a net attribute is stored in m_objectAttributesDictionary.
*/ */
void clearNetAttribute(); void clearNetAttribute();

View File

@ -60,19 +60,29 @@ public:
/// Set whether the user coordinate system is fit to content /// Set whether the user coordinate system is fit to content
void SetUserCoordsFit( bool user_coords_fit ) { fitUserCoords = user_coords_fit; } void SetUserCoordsFit( bool user_coords_fit ) { fitUserCoords = user_coords_fit; }
/**
* At the start of the HPGL plot pen speed and number are requested.
*/
virtual bool StartPlot() override; virtual bool StartPlot() override;
/**
* HPGL end of plot: sort and emit graphics, pen return and release.
*/
virtual bool EndPlot() override; virtual bool EndPlot() override;
/// HPGL doesn't handle line thickness or color /// HPGL doesn't handle line thickness or color
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override
{ {
// This is the truth // This is the truth
m_currentPenWidth = userToDeviceSize( penDiameter ); m_currentPenWidth = userToDeviceSize( penDiameter );
} }
/**
* HPGL supports dashed lines.
*/
virtual void SetDash( PLOT_DASH_TYPE dashed ) override; virtual void SetDash( PLOT_DASH_TYPE dashed ) override;
virtual void SetColor( COLOR4D color ) override {} virtual void SetColor( const COLOR4D& color ) override {}
virtual void SetPenSpeed( int speed ) virtual void SetPenSpeed( int speed )
{ {
@ -94,10 +104,23 @@ public:
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH,
void * aData = NULL ) override; void* aData = nullptr ) override;
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
OUTLINE_MODE tracemode, void* aData ) override; OUTLINE_MODE tracemode, void* aData ) override;
/**
* Plot an arc.
*
* Command
* PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, NbSegm; PU;
* Or PU PY x, y; PD start_arc_X AA, start_arc_Y, angle, PU;
*
* center is the center of the arc.
* StAngled is the start angle of the arc.
* EndAngle is end angle the arc.
* Radius is the radius of the arc.
*/
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
@ -123,9 +146,9 @@ public:
protected: protected:
/// Start a new HPGL_ITEM if necessary, keeping the current one if it exists. /// Start a new HPGL_ITEM if necessary, keeping the current one if it exists.
/// ///
/// @param location - location of the item /// @param location is the location of the item.
/// ///
/// @return whether a new item was made /// @return whether a new item was made.
bool startItem( DPOINT location ); bool startItem( DPOINT location );
/// Flush the current HPGL_ITEM and clear out the current item pointer. /// Flush the current HPGL_ITEM and clear out the current item pointer.
@ -134,8 +157,8 @@ protected:
/// Start a new HPGL_ITEM with the given string if necessary, or append the /// Start a new HPGL_ITEM with the given string if necessary, or append the
/// string to the current item. /// string to the current item.
/// ///
/// @param location - location of the item, if a new one is made /// @param location is the location of the item, if a new one is made.
/// @param content - content substring /// @param content is the content substring.
/// ///
/// @return whether a new item was made /// @return whether a new item was made
bool startOrAppendItem( DPOINT location, wxString const& content ); bool startOrAppendItem( DPOINT location, wxString const& content );

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software: you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
@ -32,9 +32,8 @@
/** /**
* The PSLIKE_PLOTTER class is an intermediate class to handle common * The PSLIKE_PLOTTER class is an intermediate class to handle common routines for engines
* routines for engines working more or less with the postscript imaging * working more or less with the postscript imaging model.
* model
*/ */
class PSLIKE_PLOTTER : public PLOTTER class PSLIKE_PLOTTER : public PLOTTER
{ {
@ -69,9 +68,8 @@ public:
OUTLINE_MODE aTraceMode, void* aData ) override; OUTLINE_MODE aTraceMode, void* aData ) override;
virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient, virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient,
OUTLINE_MODE aTraceMode, void* aData ) override; OUTLINE_MODE aTraceMode, void* aData ) override;
virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient,
double aPadOrient, OUTLINE_MODE aTraceMode, OUTLINE_MODE aTraceMode, void* aData ) override;
void* aData ) override;
virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
int aCornerRadius, double aOrient, int aCornerRadius, double aOrient,
OUTLINE_MODE aTraceMode, void* aData ) override; OUTLINE_MODE aTraceMode, void* aData ) override;
@ -81,16 +79,25 @@ public:
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) override; double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) override;
virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount, virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount,
double aOrient, OUTLINE_MODE aTraceMode, void* aData ) override; double aOrient, OUTLINE_MODE aTraceMode,
void* aData ) override;
/** /**
* The SetColor implementation is split with the subclasses: * The SetColor implementation is split with the subclasses:
* The PSLIKE computes the rgb values, the subclass emits the * The PSLIKE computes the rgb values, the subclass emits the
* operator to actually do it * operator to actually do it
*/ */
virtual void SetColor( COLOR4D color ) override; virtual void SetColor( const COLOR4D& color ) override;
protected: protected:
/**
* This is the core for postscript/PDF text alignment.
*
* It computes the transformation matrix to generate a user space
* system aligned with the text. Even the PS uses the concat
* operator to simplify PDF generation (concat is everything PDF
* has to modify the CTM. Lots of parameters, both in and out.
*/
void computeTextParameters( const wxPoint& aPos, void computeTextParameters( const wxPoint& aPos,
const wxString& aText, const wxString& aText,
int aOrient, int aOrient,
@ -109,8 +116,14 @@ protected:
double *ctm_e, double *ctm_e,
double *ctm_f, double *ctm_f,
double *heightFactor ); double *heightFactor );
void postscriptOverlinePositions( const wxString& aText, int aXSize,
bool aItalic, bool aBold, /**
* Computes the x coordinates for the overlining in a string of text.
* Fills the passed vector with couples of (start, stop) values to be
* used in the text coordinate system (use computeTextParameters to
* obtain the parameters to establish such a system)
*/
void postscriptOverlinePositions( const wxString& aText, int aXSize, bool aItalic, bool aBold,
std::vector<int> *pos_pairs ); std::vector<int> *pos_pairs );
/// convert a wxString unicode string to a char string compatible with the accepted /// convert a wxString unicode string to a char string compatible with the accepted
@ -123,8 +136,13 @@ protected:
/// Height of the postscript font (from the AFM) /// Height of the postscript font (from the AFM)
static const double postscriptTextAscent; // = 0.718; static const double postscriptTextAscent; // = 0.718;
int returnPostscriptTextWidth( const wxString& aText, int aXSize, /**
bool aItalic, bool aBold ); * Sister function for the GraphicTextWidth in drawtxt.cpp
* Does the same processing (i.e. calculates a text string width) but
* using postscript metrics for the Helvetica font (optionally used for
* PS and PDF plotting
*/
int returnPostscriptTextWidth( const wxString& aText, int aXSize, bool aItalic, bool aBold );
/// Fine user scale adjust ( = 1.0 if no correction) /// Fine user scale adjust ( = 1.0 if no correction)
double plotScaleAdjX, plotScaleAdjY; double plotScaleAdjX, plotScaleAdjY;
@ -154,13 +172,34 @@ public:
return PLOT_FORMAT::POST; return PLOT_FORMAT::POST;
} }
/**
* The code within this function (and the CloseFilePS function)
* creates postscript files whose contents comply with Adobe's
* Document Structuring Convention, as documented by assorted
* details described within the following URLs:
*
* http://en.wikipedia.org/wiki/Document_Structuring_Conventions
* http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf
*
*
* BBox is the boundary box (position and size of the "client rectangle"
* for drawings (page - margins) in mils (0.001 inch)
*/
virtual bool StartPlot() override; virtual bool StartPlot() override;
virtual bool EndPlot() override; virtual bool EndPlot() override;
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override;
/**
* Set the current line width (in IUs) for the next plot.
*/
virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override;
/**
* PostScript supports dashed lines.
*/
virtual void SetDash( PLOT_DASH_TYPE dashed ) override; virtual void SetDash( PLOT_DASH_TYPE dashed ) override;
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill, virtual void Circle( const wxPoint& pos, int diametre, FILL_TYPE fill,
@ -168,16 +207,18 @@ public:
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override; int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ) override;
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
void * aData = NULL ) override;
/**
* PostScript-likes at the moment are the only plot engines supporting bitmaps.
*/
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos, virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
double aScaleFactor ) override; double aScaleFactor ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
virtual void Text( const wxPoint& aPos, virtual void Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -187,7 +228,7 @@ public:
bool aItalic, bool aItalic,
bool aBold, bool aBold,
bool aMultilineAllowed = false, bool aMultilineAllowed = false,
void* aData = NULL ) override; void* aData = nullptr ) override;
protected: protected:
virtual void emitSetRGBColor( double r, double g, double b ) override; virtual void emitSetRGBColor( double r, double g, double b ) override;
}; };
@ -216,31 +257,30 @@ public:
} }
/** /**
* Open or create the plot file aFullFilename * Open or create the plot file aFullFilename.
* *
* The base class open the file in text mode, so we should have this * The base class open the file in text mode, so we should have this
* function overlaid for PDF files, which are binary files * function overlaid for PDF files, which are binary files.
* *
* @param aFullFilename = the full file name of the file to create * @param aFullFilename is the full file name of the file to create.
* @return true if success, false if the file cannot be created/opened * @return true if success, false if the file cannot be created/opened.
*/ */
virtual bool OpenFile( const wxString& aFullFilename ) override; virtual bool OpenFile( const wxString& aFullFilename ) override;
/** /**
* The PDF engine supports multiple pages; the first one is opened * The PDF engine supports multiple pages; the first one is opened 'for free' the following
* 'for free' the following are to be closed and reopened. Between * are to be closed and reopened. Between each page parameters can be set.
* each page parameters can be set
*/ */
virtual bool StartPlot() override; virtual bool StartPlot() override;
virtual bool EndPlot() override; virtual bool EndPlot() override;
/** /**
* Starts a new page in the PDF document * Start a new page in the PDF document.
*/ */
virtual void StartPage(); virtual void StartPage();
/** /**
* Close the current page in the PDF document (and emit its compressed stream) * Close the current page in the PDF document (and emit its compressed stream).
*/ */
virtual void ClosePage(); virtual void ClosePage();
@ -252,7 +292,7 @@ public:
* Note pen width = 0 is used in plot polygons to plot filled polygons with no outline * Note pen width = 0 is used in plot polygons to plot filled polygons with no outline
* thickness. Use in this case pen width = 1 does not actually change the polygon. * thickness. Use in this case pen width = 1 does not actually change the polygon.
*/ */
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override; virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override;
/** /**
* PDF supports dashed lines * PDF supports dashed lines
@ -264,10 +304,10 @@ public:
* with the outputFile open (but not inside a page stream!) * with the outputFile open (but not inside a page stream!)
*/ */
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) override; double aScale, bool aMirror ) override;
/** /**
* Rectangles in PDF. Supported by the native operator * Rectangles in PDF. Supported by the native operator.
*/ */
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill, virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_TYPE fill,
int width = USE_DEFAULT_LINE_WIDTH ) override; int width = USE_DEFAULT_LINE_WIDTH ) override;
@ -288,14 +328,13 @@ public:
/** /**
* Polygon plotting for PDF. Everything is supported * Polygon plotting for PDF. Everything is supported
*/ */
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
void * aData = NULL ) override;
virtual void PenTo( const wxPoint& pos, char plume ) override; virtual void PenTo( const wxPoint& pos, char plume ) override;
virtual void Text( const wxPoint& aPos, virtual void Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -305,7 +344,7 @@ public:
bool aItalic, bool aItalic,
bool aBold, bool aBold,
bool aMultilineAllowed = false, bool aMultilineAllowed = false,
void* aData = NULL ) override; void* aData = nullptr ) override;
/** /**
* PDF images are handles as inline, not XObject streams... * PDF images are handles as inline, not XObject streams...
*/ */
@ -360,13 +399,13 @@ protected:
*/ */
void closePdfStream(); void closePdfStream();
int pageTreeHandle; /// Handle to the root of the page tree object int pageTreeHandle; /// Handle to the root of the page tree object
int fontResDictHandle; /// Font resource dictionary int fontResDictHandle; /// Font resource dictionary
std::vector<int> pageHandles;/// Handles to the page objects std::vector<int> pageHandles;/// Handles to the page objects
int pageStreamHandle; /// Handle of the page content object int pageStreamHandle; /// Handle of the page content object
int streamLengthHandle; /// Handle to the deferred stream length int streamLengthHandle; /// Handle to the deferred stream length
wxString workFilename; wxString workFilename;
FILE* workFile; /// Temporary file to construct the stream before zipping FILE* workFile; /// Temporary file to construct the stream before zipping
std::vector<long> xrefTable; /// The PDF xref offset table std::vector<long> xrefTable; /// The PDF xref offset table
}; };
@ -386,10 +425,22 @@ public:
return PLOT_FORMAT::SVG; return PLOT_FORMAT::SVG;
} }
virtual void SetColor( COLOR4D color ) override; virtual void SetColor( const COLOR4D& color ) override;
/**
* Create SVG file header.
*/
virtual bool StartPlot() override; virtual bool StartPlot() override;
virtual bool EndPlot() override; virtual bool EndPlot() override;
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override;
/**
* Set the current line width (in IUs) for the next plot.
*/
virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) override;
/**
* SVG supports dashed lines.
*/
virtual void SetDash( PLOT_DASH_TYPE dashed ) override; virtual void SetDash( PLOT_DASH_TYPE dashed ) override;
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
@ -408,8 +459,11 @@ public:
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, FILL_TYPE aFill, int aWidth = USE_DEFAULT_LINE_WIDTH,
void * aData = NULL ) override; void * aData = nullptr ) override;
/**
* PostScript-likes at the moment are the only plot engines supporting bitmaps.
*/
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos, virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
double aScaleFactor ) override; double aScaleFactor ) override;
@ -443,7 +497,7 @@ public:
virtual void EndBlock( void* aData ) override; virtual void EndBlock( void* aData ) override;
virtual void Text( const wxPoint& aPos, virtual void Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -453,9 +507,28 @@ public:
bool aItalic, bool aItalic,
bool aBold, bool aBold,
bool aMultilineAllowed = false, bool aMultilineAllowed = false,
void* aData = NULL ) override; void* aData = nullptr ) override;
protected: protected:
/**
* Initialize m_pen_rgb_color from reduced values r, g ,b
* ( reduced values are 0.0 to 1.0 )
*/
virtual void emitSetRGBColor( double r, double g, double b ) override;
/**
* Output the string which define pen and brush color, shape, transparency
*
* @param aIsGroup If false, do not form a new group for the style.
* @param aExtraStyle If given, the string will be added into the style string before closing
*/
void setSVGPlotStyle( bool aIsGroup = true, const std::string& aExtraStyle = {} );
/**
* Prepare parameters for setSVGPlotStyle()
*/
void setFillMode( FILL_TYPE fill );
FILL_TYPE m_fillMode; // true if the current contour FILL_TYPE m_fillMode; // true if the current contour
// rect, arc, circle, polygon must be filled // rect, arc, circle, polygon must be filled
long m_pen_rgb_color; // current rgb color value: each color has long m_pen_rgb_color; // current rgb color value: each color has
@ -475,23 +548,4 @@ protected:
// Use 3-6 (3 means um precision, 6 nm precision) in PcbNew // Use 3-6 (3 means um precision, 6 nm precision) in PcbNew
// 3-4 in other modules (avoid values >4 to avoid overflow) // 3-4 in other modules (avoid values >4 to avoid overflow)
// see also comment for m_useInch. // see also comment for m_useInch.
/**
* Initialize m_pen_rgb_color from reduced values r, g ,b
* ( reduced values are 0.0 to 1.0 )
*/
virtual void emitSetRGBColor( double r, double g, double b ) override;
/**
* Output the string which define pen and brush color, shape, transparency
*
* @param aIsGroup If false, do not form a new group for the style.
* @param aExtraStyle If given, the string will be added into the style string before closing
*/
void setSVGPlotStyle( bool aIsGroup = true, const std::string& aExtraStyle = {} );
/**
* Prepare parameters for setSVGPlotStyle()
*/
void setFillMode( FILL_TYPE fill );
}; };

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -147,7 +147,8 @@ public:
/** /**
* Plot in B/W or color. * Plot in B/W or color.
* @param aColorMode = true to plot in color, false to plot in black and white *
* @param aColorMode use true to plot in color, false to plot in black and white.
*/ */
virtual void SetColorMode( bool aColorMode ) { m_colorMode = aColorMode; } virtual void SetColorMode( bool aColorMode ) { m_colorMode = aColorMode; }
bool GetColorMode() const { return m_colorMode; } bool GetColorMode() const { return m_colorMode; }
@ -160,13 +161,14 @@ public:
/** /**
* Set the line width for the next drawing. * Set the line width for the next drawing.
* @param width is specified in IUs *
* @param aData is an auxiliary parameter, mainly used in gerber plotter * @param width is specified in IUs.
* @param aData is an auxiliary parameter, mainly used in gerber plotter.
*/ */
virtual void SetCurrentLineWidth( int width, void* aData = NULL ) = 0; virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) = 0;
virtual int GetCurrentLineWidth() const { return m_currentPenWidth; } virtual int GetCurrentLineWidth() const { return m_currentPenWidth; }
virtual void SetColor( COLOR4D color ) = 0; virtual void SetColor( const COLOR4D& color ) = 0;
virtual void SetDash( PLOT_DASH_TYPE dashed ) = 0; virtual void SetDash( PLOT_DASH_TYPE dashed ) = 0;
@ -175,7 +177,8 @@ public:
virtual void SetTitle( const wxString& aTitle ) { m_title = aTitle; } virtual void SetTitle( const wxString& aTitle ) { m_title = aTitle; }
/** /**
* Add a line to the list of free lines to print at the beginning of the file * Add a line to the list of free lines to print at the beginning of the file.
*
* @param aExtraString is the string to print * @param aExtraString is the string to print
*/ */
void AddLineToHeader( const wxString& aExtraString ) void AddLineToHeader( const wxString& aExtraString )
@ -193,20 +196,22 @@ public:
/** /**
* Set the plot offset and scaling for the current plot * Set the plot offset and scaling for the current plot
* @param aOffset is the plot offset *
* @param aOffset is the plot offset.
* @param aIusPerDecimil gives the scaling factor from IUs to device units * @param aIusPerDecimil gives the scaling factor from IUs to device units
* @param aScale is the user set plot scaling factor (either explicitly * @param aScale is the user set plot scaling factor (either explicitly
* or using 'fit to A4') * or using 'fit to A4').
* @param aMirror flips the plot in the Y direction (useful for toner * @param aMirror flips the plot in the Y direction (useful for toner
* transfers or some kind of film) * transfers or some kind of film).
*/ */
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) = 0; double aScale, bool aMirror ) = 0;
/** /**
* Open or create the plot file aFullFilename * Open or create the plot file \a aFullFilename.
* @param aFullFilename = the full file name of the file to create *
* @return true if success, false if the file cannot be created/opened * @param aFullFilename is the full file name of the file to create.
* @return true if success, false if the file cannot be created/opened.
* *
* Virtual because some plotters use ascii files, some others binary files (PDF) * Virtual because some plotters use ascii files, some others binary files (PDF)
* The base class open the file in text mode * The base class open the file in text mode
@ -230,7 +235,7 @@ public:
int width = USE_DEFAULT_LINE_WIDTH ) = 0; int width = USE_DEFAULT_LINE_WIDTH ) = 0;
/** /**
* Generic fallback: arc rendered as a polyline * Generic fallback: arc rendered as a polyline.
*/ */
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH ); int rayon, FILL_TYPE fill, int width = USE_DEFAULT_LINE_WIDTH );
@ -243,15 +248,15 @@ public:
*/ */
virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1, virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
const wxPoint& aControl2, const wxPoint& aEnd, const wxPoint& aControl2, const wxPoint& aEnd,
int aTolerance, int aTolerance, int aLineThickness = USE_DEFAULT_LINE_WIDTH );
int aLineThickness = USE_DEFAULT_LINE_WIDTH );
/** /**
* moveto/lineto primitive, moves the 'pen' to the specified direction * Moveto/lineto primitive, moves the 'pen' to the specified direction.
* @param pos is the target position *
* @param pos is the target position.
* @param plume specifies the kind of motion: 'U' only moves the pen, * @param plume specifies the kind of motion: 'U' only moves the pen,
* 'D' draw a line from the current position and 'Z' finish * 'D' draw a line from the current position and 'Z' finish
* the drawing and returns the 'pen' to rest (flushes the trace) * the drawing and returns the 'pen' to rest (flushes the trace).
*/ */
virtual void PenTo( const wxPoint& pos, char plume ) = 0; virtual void PenTo( const wxPoint& pos, char plume ) = 0;
@ -279,39 +284,38 @@ public:
} }
/** /**
* Draw a polygon ( filled or not ) * Draw a polygon ( filled or not ).
* @param aCornerList = corners list (a std::vector< wxPoint >) *
* @param aFill = type of fill * @param aCornerList is the corners list (a std::vector< wxPoint >).
* @param aWidth = line width * @param aFill is the type of fill.
* @param aData an auxiliary info (mainly for gerber format) * @param aWidth is the line width.
* @param aData is an auxiliary info (mainly for gerber format).
*/ */
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_TYPE aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = NULL ) = 0; int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) = 0;
/** /**
* Draw a polygon ( filled or not ) * Draw a polygon ( filled or not ).
* @param aCornerList = corners list (a SHAPE_LINE_CHAIN). * @param aCornerList is the corners list (a SHAPE_LINE_CHAIN).
* must be closed (IsClosed() == true) for a polygon. Otherwise this is a polyline * must be closed (IsClosed() == true) for a polygon. Otherwise this is a polyline.
* @param aFill = type of fill * @param aFill is the type of fill.
* @param aWidth = line width * @param aWidth is the line width.
* @param aData an auxiliary info (mainly for gerber format) * @param aData is an auxiliary info (mainly for gerber format).
*/ */
virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill, virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_TYPE aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = NULL ); int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr );
/** /**
* Only PostScript plotters can plot bitmaps. * Only PostScript plotters can plot bitmaps.
* *
* A rectangle is plotted for plotters that cannot plot a bitmap. * A rectangle is plotted for plotters that cannot plot a bitmap.
* *
* @brief Draw an image bitmap * @param aImage is the bitmap.
* @param aImage = the bitmap * @param aPos is position of the center of the bitmap.
* @param aPos = position of the center of the bitmap * @param aScaleFactor is the scale factor to apply to the bitmap size
* @param aScaleFactor = the scale factor to apply to the bitmap size * (this is not the plot scale factor).
* (this is not the plot scale factor)
*/ */
virtual void PlotImage( const wxImage & aImage, const wxPoint& aPos, virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor );
double aScaleFactor );
// Higher level primitives -- can be drawn as line, sketch or 'filled' // Higher level primitives -- can be drawn as line, sketch or 'filled'
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
@ -329,89 +333,93 @@ public:
// Flash primitives // Flash primitives
/** /**
* @param aPadPos Position of the shape (center of the rectangle * @param aPadPos Position of the shape (center of the rectangle.
* @param aDiameter diameter of round pad * @param aDiameter is the diameter of round pad.
* @param aTraceMode FILLED or SKETCH * @param aTraceMode is the drawing mode, FILLED or SKETCH.
* @param aData an auxiliary info (mainly for gerber format attributes) * @param aData is an auxiliary info (mainly for gerber format attributes).
*/ */
virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter, virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
OUTLINE_MODE aTraceMode, void* aData ) = 0; OUTLINE_MODE aTraceMode, void* aData ) = 0;
/** /**
* @param aPadPos Position of the shape (center of the rectangle * @param aPadPos Position of the shape (center of the rectangle.
* @param aSize = size of oblong shape * @param aSize is the size of oblong shape.
* @param aPadOrient The rotation of the shape * @param aPadOrient The rotation of the shape.
* @param aTraceMode FILLED or SKETCH * @param aTraceMode is the drawing mode, FILLED or SKETCH.
* @param aData an auxiliary info (mainly for gerber format attributes) * @param aData an auxiliary info (mainly for gerber format attributes).
*/ */
virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient, virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient,
OUTLINE_MODE aTraceMode, void* aData ) = 0; OUTLINE_MODE aTraceMode, void* aData ) = 0;
/** /**
* @param aPadPos Position of the shape (center of the rectangle * @param aPadPos Position of the shape (center of the rectangle).
* @param aSize = size of rounded rect * @param aSize is the size of rounded rect.
* @param aPadOrient The rotation of the shape * @param aPadOrient The rotation of the shape.
* @param aTraceMode FILLED or SKETCH * @param aTraceMode is the drawing mode, FILLED or SKETCH.
* @param aData an auxiliary info (mainly for gerber format attributes) * @param aData an auxiliary info (mainly for gerber format attributes).
*/ */
virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize,
double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) = 0; double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) = 0;
/** /**
* @param aPadPos Position of the shape (center of the rectangle * @param aPadPos Position of the shape (center of the rectangle.
* @param aSize = size of rounded rect * @param aSize is the size of rounded rect.
* @param aCornerRadius Radius of the rounded corners * @param aCornerRadius Radius of the rounded corners.
* @param aOrient The rotation of the shape * @param aOrient The rotation of the shape.
* @param aTraceMode FILLED or SKETCH * @param aTraceMode is the drawing mode, FILLED or SKETCH.
* @param aData an auxiliary info (mainly for gerber format attributes) * @param aData an auxiliary info (mainly for gerber format attributes).
*/ */
virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
int aCornerRadius, double aOrient, int aCornerRadius, double aOrient,
OUTLINE_MODE aTraceMode, void* aData ) = 0; OUTLINE_MODE aTraceMode, void* aData ) = 0;
/** /**
* @param aPadPos Position of the shape * @param aPadPos Position of the shape.
* @param aSize = size of round reference pad * @param aSize is the size of round reference pad.
* @param aPadOrient = pad rotation, used only with aperture macros (Gerber plotter) * @param aPadOrient is the pad rotation, used only with aperture macros (Gerber plotter).
* @param aPolygons the shape as polygon set * @param aPolygons the shape as polygon set.
* @param aTraceMode FILLED or SKETCH * @param aTraceMode is the drawing mode, FILLED or SKETCH.
* @param aData an auxiliary info (mainly for gerber format attributes) * @param aData an auxiliary info (mainly for gerber format attributes).
*/ */
virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
double aPadOrient, SHAPE_POLY_SET* aPolygons, double aPadOrient, SHAPE_POLY_SET* aPolygons,
OUTLINE_MODE aTraceMode, void* aData ) = 0; OUTLINE_MODE aTraceMode, void* aData ) = 0;
/** /**
* Flash a trapezoidal pad * Flash a trapezoidal pad.
* @param aPadPos = the position of the shape *
* @param aCorners = the list of 4 corners positions, * @param aPadPos is the the position of the shape.
* relative to the shape position, pad orientation 0 * @param aCorners is the list of 4 corners positions, relative to the shape position,
* @param aPadOrient = the rotation of the shape * pad orientation 0.
* @param aTraceMode = FILLED or SKETCH * @param aPadOrient is the rotation of the shape.
* @param aData an auxiliary info (mainly for gerber format attributes) * @param aTraceMode is the drawing mode, FILLED or SKETCH.
* @param aData an auxiliary info (mainly for gerber format attributes).
*/ */
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, OUTLINE_MODE aTraceMode, double aPadOrient, OUTLINE_MODE aTraceMode,
void* aData ) = 0; void* aData ) = 0;
/** /**
* Flash a regular polygon. Useful only in Gerber files to flash a regular polygon * Flash a regular polygon. Useful only in Gerber files to flash a regular polygon.
* @param aShapePos is the center of the circle containing the polygon *
* @param aRadius is the radius of the circle containing the polygon * @param aShapePos is the center of the circle containing the polygon.
* @param aCornerCount is the number of vertices * @param aRadius is the radius of the circle containing the polygon.
* @param aOrient is the polygon rotation in degrees * @param aCornerCount is the number of vertices.
* @param aOrient is the polygon rotation in degrees.
* @param aData is a auxiliary parameter used (if needed) to handle extra info * @param aData is a auxiliary parameter used (if needed) to handle extra info
* specific to the plotter * specific to the plotter.
*/ */
virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount, virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount,
double aOrient, OUTLINE_MODE aTraceMode, void* aData ) = 0 ; double aOrient, OUTLINE_MODE aTraceMode, void* aData ) = 0 ;
/** /**
* Draws text with the plotter. For convenience it accept the color to use * Draw text with the plotter.
* for specific plotters (GERBER) aData is used to pass extra parameters *
* For convenience it accept the color to use for specific plotters (GERBER) aData is used
* to pass extra parameters.
*/ */
virtual void Text( const wxPoint& aPos, virtual void Text( const wxPoint& aPos,
const COLOR4D aColor, const COLOR4D& aColor,
const wxString& aText, const wxString& aText,
double aOrient, double aOrient,
const wxSize& aSize, const wxSize& aSize,
@ -421,17 +429,19 @@ public:
bool aItalic, bool aItalic,
bool aBold, bool aBold,
bool aMultilineAllowed = false, bool aMultilineAllowed = false,
void* aData = NULL ); void* aData = nullptr );
/** /**
* Draw a marker (used for the drill map) * Draw a marker (used for the drill map).
*/ */
static const unsigned MARKER_COUNT = 58; static const unsigned MARKER_COUNT = 58;
/** /**
* Draw a pattern shape number aShapeId, to coord position. * Draw a pattern shape number aShapeId, to coord position.
* Diameter diameter = (coord table) hole *
* AShapeId = index (used to generate forms characters) * @param aPosition is the position of the marker.
* @param aDiameter is the diameter of the marker.
* @param aShapeId is the index (used to generate forms characters).
*/ */
void Marker( const wxPoint& position, int diametre, unsigned aShapeId ); void Marker( const wxPoint& position, int diametre, unsigned aShapeId );
@ -439,6 +449,7 @@ public:
* Set the current Gerber layer polarity to positive or negative * Set the current Gerber layer polarity to positive or negative
* by writing \%LPD*\% or \%LPC*\% to the Gerber file, respectively. * by writing \%LPD*\% or \%LPC*\% to the Gerber file, respectively.
* (obviously starts a new Gerber layer, too) * (obviously starts a new Gerber layer, too)
*
* @param aPositive is the layer polarity and true for positive. * @param aPositive is the layer polarity and true for positive.
* It's not useful with most other plotter since they can't 'scratch' * It's not useful with most other plotter since they can't 'scratch'
* the film like photoplotter imagers do * the film like photoplotter imagers do
@ -450,7 +461,7 @@ public:
/** /**
* Change the current text mode. See the PlotTextMode * Change the current text mode. See the PlotTextMode
* explanation at the beginning of the file * explanation at the beginning of the file.
*/ */
virtual void SetTextMode( PLOT_TEXT_MODE mode ) virtual void SetTextMode( PLOT_TEXT_MODE mode )
{ {
@ -536,21 +547,19 @@ protected:
// Coordinate and scaling conversion functions // Coordinate and scaling conversion functions
/** /**
* Modifies coordinates according to the orientation, * Modify coordinates according to the orientation, scale factor, and offsets trace. Also
* scale factor, and offsets trace. Also convert from a wxPoint to DPOINT, * convert from a wxPoint to DPOINT, since some output engines needs floating point
* since some output engines needs floating point coordinates. * coordinates.
*/ */
virtual DPOINT userToDeviceCoordinates( const wxPoint& aCoordinate ); virtual DPOINT userToDeviceCoordinates( const wxPoint& aCoordinate );
/** /**
* Modifies size according to the plotter scale factors * Modify size according to the plotter scale factors (wxSize version, returns a DPOINT).
* (wxSize version, returns a DPOINT)
*/ */
virtual DPOINT userToDeviceSize( const wxSize& size ); virtual DPOINT userToDeviceSize( const wxSize& size );
/** /**
* Modifies size according to the plotter scale factors * Modify size according to the plotter scale factors (simple double version).
* (simple double version)
*/ */
virtual double userToDeviceSize( double size ) const; virtual double userToDeviceSize( double size ) const;