Commit bc0d79d5 authored by jean-pierre charras's avatar jean-pierre charras

finished Draw functions for aperture macros. Now aperture macros are drawn correctly.

 Known bug: aperture macros having parameters are incorrect: parameters are not transmited correctly. Work still in progress.
parent e0617666
......@@ -4,6 +4,14 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with
email address.
2010-oct-03, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++gerbview:
finished Draw functions for aperture macros.
Now aperture macros are draww correctly.
Known bug: aperture macros having parameters are incorrect: parameters are not transmited correctly.
Work still in progress.
2010-sept-28, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++gerbview:
......
......@@ -40,29 +40,103 @@
* @return wxPoint - The gerbview coordinate system vector.
*/
extern wxPoint mapPt( double x, double y, bool isMetric ); // defined it rs274d.cpp
/**
* Function scale
* converts a distance given in floating point to our deci-mils
*/
extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp
extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp
/**
* Function mapExposure
* translates the first parameter from an aperture macro into a current
* exposure setting.
* @param aParent = a GERBER_DRAW_ITEM that handle:
* ** m_Exposure A dynamic setting which can change throughout the
* reading of the gerber file, and it indicates whether the current tool
* is lit or not.
* ** m_ImageNegative A dynamic setting which can change throughout the reading
* of the gerber file, and it indicates whether the current D codes are to
* be interpreted as erasures or not.
* @return true to draw with current color, false to draw with alt color (erase)
*/
bool AM_PRIMITIVE::mapExposure( GERBER_DRAW_ITEM* aParent )
{
bool exposure;
switch( primitive_id )
{
case AMP_CIRCLE:
case AMP_LINE2:
case AMP_LINE20:
case AMP_LINE_CENTER:
case AMP_LINE_LOWER_LEFT:
case AMP_OUTLINE:
case AMP_THERMAL:
case AMP_POLYGON:
// All have an exposure parameter and can return true or false
switch( GetExposure() )
{
case 0: // exposure always OFF
exposure = false;
break;
default:
case 1: // exposure always OON
exposure = true;
break;
case 2: // reverse exposure
exposure = !aParent->m_LayerNegative;
}
break;
case AMP_MOIRE:
case AMP_EOF:
case AMP_UNKNOWN:
default:
return true; // All have no exposure parameter and must return true (no change for exposure)
break;
}
return exposure ^ aParent->m_ImageNegative;
}
/**
* Function GetExposure
* returns the first parameter in integer form. Some but not all primitives
* use the first parameter as an exposure control.
*/
int AM_PRIMITIVE::GetExposure() const
{
// No D_CODE* for GetValue()
wxASSERT( params.size() && params[0].IsImmediate() );
return (int) params[0].GetValue( NULL );
}
/** function DrawBasicShape
* Draw the primitive shape for flashed items.
*/
void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
EDA_Rect* aClipBox,
wxDC* aDC,
int aColor,
wxPoint aShapePos,
bool aFilledShape )
EDA_Rect* aClipBox,
wxDC* aDC,
int aColor, int aAltColor,
wxPoint aShapePos,
bool aFilledShape )
{
static std::vector<wxPoint> polybuffer; // create a static buffer to avoid a lot of memory reallocation
polybuffer.clear();
wxPoint curPos = aShapePos;
D_CODE* tool = aParent->GetDcodeDescr();
bool gerberMetric = aParent->m_UnitsMetric;
D_CODE* tool = aParent->GetDcodeDescr();
bool gerberMetric = aParent->m_UnitsMetric;
int rotation;
if( mapExposure( aParent ) == false )
{
EXCHG(aColor, aAltColor);
}
switch( primitive_id )
{
case AMP_CIRCLE: // Circle, given diameter and position
......@@ -70,9 +144,8 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
/* Generated by an aperture macro declaration like:
* "1,1,0.3,0.5, 1.0*"
* type (1), exposure, diameter, pos.x, pos.y
* type is not stored in parameters list, so the first parameter is pos.x
* type is not stored in parameters list, so the first parameter is exposure
*/
int exposure = params[0].GetValue( tool );
curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), gerberMetric );
int radius = scale( params[1].GetValue( tool ), gerberMetric ) / 2;
if( !aFilledShape )
......@@ -88,22 +161,24 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
/* Generated by an aperture macro declaration like:
* "2,1,0.3,0,0, 0.5, 1.0,-135*"
* type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
* type is not stored in parameters list, so the first parameter is pos.x
* type is not stored in parameters list, so the first parameter is exposure
*/
int exposure = params[0].GetValue( tool );
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
int rotation = wxRound(params[6].GetValue( tool ) * 10.0);
if (rotation)
rotation = wxRound( params[6].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
RotatePoint(&polybuffer[ii], rotation);
RotatePoint( &polybuffer[ii], rotation );
}
// Move to current position:
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
polybuffer[ii] += curPos;
GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
GRClosedPoly( aClipBox, aDC,
polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
}
break;
......@@ -112,21 +187,24 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
/* Generated by an aperture macro declaration like:
* "21,1,0.3,0.03,0,0,-135*"
* type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
* type is not stored in parameters list, so the first parameter is pos.x
* type is not stored in parameters list, so the first parameter is exposure
*/
int exposure = params[0].GetValue( tool );
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
int rotation = wxRound(params[5].GetValue( tool ) * 10.0);
if (rotation)
rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
RotatePoint(&polybuffer[ii], rotation);
RotatePoint( &polybuffer[ii], rotation );
}
// Move to current position:
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
polybuffer[ii] += curPos;
GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
GRClosedPoly( aClipBox, aDC,
polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
}
break;
......@@ -135,44 +213,64 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
/* Generated by an aperture macro declaration like:
* "22,1,0.3,0.03,0,0,-135*"
* type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
* type is not stored in parameters list, so the first parameter is pos.x
* type is not stored in parameters list, so the first parameter is exposure
*/
int exposure = params[0].GetValue( tool );
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
int rotation = wxRound(params[5].GetValue( tool ) * 10.0);
if (rotation)
rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
RotatePoint(&polybuffer[ii], rotation);
RotatePoint( &polybuffer[ii], rotation );
}
// Move to current position:
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
polybuffer[ii] += curPos;
GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
GRClosedPoly( aClipBox, aDC,
polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
}
break;
case AMP_THERMAL:
{
/* Generated by an aperture macro declaration like:
* "7,0,0,1.0,0.3,0.01,-13*"
* "7, 0,0,1.0,0.3,0.01,-13*"
* type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
* type is not stored in parameters list, so the first parameter is pos.x
* type is not stored in parameters list, so the first parameter is center.x
*/
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), gerberMetric );
/* int outerRadius = scale( params[2].GetValue( tool ), gerberMetric ) / 2;
if( !aFilledShape )
GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerRadius, aColor );
else
GRFilledCircle( aClipBox, aDC, curPos, outerRadius, aColor );
*/
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
int rotation = wxRound(params[6].GetValue( tool ) * 10.0);
if (rotation)
rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
// Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer.
// We must draw 4 sub-shapes rotated by 90 deg
std::vector<wxPoint> subshape_poly;
for( int ii = 0; ii < 4; ii++ )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
RotatePoint(&polybuffer[ii], rotation);
subshape_poly = polybuffer;
int sub_rotation = rotation + 900 * ii;
for( unsigned jj = 0; jj < subshape_poly.size(); jj++ )
RotatePoint( &subshape_poly[jj], sub_rotation );
// Move to current position:
for( unsigned jj = 0; jj < subshape_poly.size(); jj++ )
subshape_poly[jj] += curPos;
GRClosedPoly( aClipBox, aDC,
subshape_poly.size(), &subshape_poly[0], true, aAltColor,
aAltColor );
}
// Move to current position:
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
polybuffer[ii] += curPos;
GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
printf(" AMP_THERMAL %d\n",polybuffer.size());
}
break;
......@@ -186,13 +284,13 @@ printf(" AMP_THERMAL %d\n",polybuffer.size());
* type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
* type is not stored in parameters list, so the first parameter is pos.x
*/
int outerDiam = scale( params[2].GetValue( tool ), gerberMetric );
int outerDiam = scale( params[2].GetValue( tool ), gerberMetric );
int penThickness = scale( params[3].GetValue( tool ), gerberMetric );
int gap = scale( params[4].GetValue( tool ), gerberMetric );
int numCircles = wxRound(params[5].GetValue( tool ));
int numCircles = wxRound( params[5].GetValue( tool ) );
// adjust outerDiam by this on each nested circle
int diamAdjust = (gap + penThickness);//*2; //Should we use * 2 ?
int diamAdjust = (gap + penThickness); //*2; //Should we use * 2 ?
for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
{
if( outerDiam <= 0 )
......@@ -200,62 +298,103 @@ printf(" AMP_THERMAL %d\n",polybuffer.size());
if( !aFilledShape )
{
// draw the border of the pen's path using two circles, each as narrow as possible
GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerDiam/2, 0, aColor );
GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerDiam/2 - penThickness, 0, aColor );
GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerDiam / 2, 0, aColor );
GRCircle( aClipBox, aDC, curPos.x, curPos.y,
outerDiam / 2 - penThickness, 0, aColor );
}
else // Filled mode
{
GRCircle( aClipBox, aDC, curPos.x, curPos.y, (outerDiam-penThickness)/2, penThickness, aColor );
GRCircle( aClipBox, aDC, curPos.x, curPos.y,
(outerDiam - penThickness) / 2, penThickness, aColor );
}
}
// Draw the cross:
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
int rotation = wxRound(params[8].GetValue( tool ) * 10.0);
if (rotation)
rotation = wxRound( params[8].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
RotatePoint(&polybuffer[ii], rotation);
RotatePoint( &polybuffer[ii], rotation );
}
// Move to current position:
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
polybuffer[ii] += curPos;
GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
GRClosedPoly( aClipBox, aDC,
polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
}
break;
break;
case AMP_OUTLINE:
#if defined(DEBUG)
{
/* Generated by an aperture macro declaration like:
* "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
* type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation
* type is not stored in parameters list, so the first parameter is exposure
*/
int numPoints = (int) params[1].GetValue( tool );
rotation = wxRound( params[numPoints * 2 + 4].GetValue( tool ) * 10.0 );
wxPoint pos;
// Read points. numPoints does not include the starting point, so add 1.
for( int i = 0; i<numPoints + 1; ++i )
{
int jj = i * 2 + 2;
pos.x = scale( params[jj].GetValue( tool ), gerberMetric );
pos.y = scale( params[jj + 1].GetValue( tool ), gerberMetric );
polybuffer.push_back(pos);
}
// rotate polygon and move it to the actual position
// shape rotation:
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
{
int exposure = params[0].GetValue( tool );
int numPoints = (int) this->params[1].GetValue( tool );
int rotation = wxRound(params[numPoints * 2 + 4].GetValue( tool ) * 10.0);
NEGATE(polybuffer[ii].y);
RotatePoint( &polybuffer[ii], rotation );
}
printf( "AMP_OUTLINE:\n" );
printf( " exposure: %g\n", exposure );
printf( " # points: %d\n", numPoints );
// Move to current position:
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
polybuffer[ii] += curPos;
// numPoints does not include the starting point, so add 1.
for( int i = 0; i<numPoints + 1; ++i )
{
printf( " [%d]: X=%g Y=%g\n", i,
this->params[i * 2 + 2 + 0].GetValue( tool ),
this->params[i * 2 + 2 + 1].GetValue( tool )
);
}
GRClosedPoly( aClipBox, aDC,
polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
}
break;
printf( " rotation: %g\n", (float)rotation/10 );
case AMP_POLYGON: // Is a regular polygon
/* Generated by an aperture macro declaration like:
* "5,1,0.6,0,0,0.5,25"
* type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
* type is not stored in parameters list, so the first parameter is exposure
*/
curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ),
gerberMetric );
// Creates the shape:
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// rotate polygon and move it to the actual position
rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
{
NEGATE(polybuffer[ii].y);
RotatePoint( &polybuffer[ii], rotation );
polybuffer[ii] += curPos;
}
#endif
GRClosedPoly( aClipBox, aDC,
polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
break;
case AMP_UNKNOWN:
case AMP_POLYGON:
case AMP_EOF:
default:
// not yet supported, waiting for you.
break;
case AMP_UNKNOWN:
default:
D( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
break;
}
}
......@@ -269,9 +408,12 @@ printf(" AMP_THERMAL %d\n",polybuffer.size());
* because circles are very easy to draw (no rotation problem) so convert them in polygons,
* and draw them as polygons is not a good idea.
*/
void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector<wxPoint>& aBuffer, bool aUnitsMetric)
void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent,
std::vector<wxPoint>& aBuffer,
bool aUnitsMetric )
{
D_CODE* tool = aParent->GetDcodeDescr();
D_CODE* tool = aParent->GetDcodeDescr();
switch( primitive_id )
{
case AMP_CIRCLE: // Circle, currently convertion not needed
......@@ -280,31 +422,33 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector
case AMP_LINE2:
case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
{
int width = scale( this->params[1].GetValue( tool ), aUnitsMetric );
wxPoint start = mapPt( this->params[2].GetValue( tool ),
this->params[3].GetValue( tool ), aUnitsMetric );
wxPoint end = mapPt( this->params[4].GetValue( tool ),
this->params[5].GetValue( tool ), aUnitsMetric );
int width = scale( params[1].GetValue( tool ), aUnitsMetric );
wxPoint start = mapPt( params[2].GetValue( tool ),
params[3].GetValue( tool ), aUnitsMetric );
wxPoint end = mapPt( params[4].GetValue( tool ),
params[5].GetValue( tool ), aUnitsMetric );
wxPoint delta = end - start;
int len = wxRound(hypot(delta.x, delta.y));
int len = wxRound( hypot( delta.x, delta.y ) );
// To build the polygon, we must create a horizonta polygon starting to "start"
// and rotate it to have it end point to "end"
wxPoint currpt;
currpt.y += width/2; // Upper left
aBuffer.push_back(currpt);
currpt.x = len; // Upper right
aBuffer.push_back(currpt);
currpt.y -= width; // lower right
aBuffer.push_back(currpt);
currpt.x = 0; // Upper left
aBuffer.push_back(currpt);
currpt.y += width / 2; // Upper left
aBuffer.push_back( currpt );
currpt.x = len; // Upper right
aBuffer.push_back( currpt );
currpt.y -= width; // lower right
aBuffer.push_back( currpt );
currpt.x = 0; // Upper left
aBuffer.push_back( currpt );
// Rotate rectangle and move it to the actual start point
int angle = wxRound( atan2(delta.y, delta.x) * 1800.0 / M_PI );
int angle = wxRound( atan2( delta.y, delta.x ) * 1800.0 / M_PI );
for( unsigned ii = 0; ii < 4; ii++ )
{
RotatePoint(&aBuffer[ii], -angle);
RotatePoint( &aBuffer[ii], -angle );
aBuffer[ii] += start;
NEGATE(aBuffer[ii].y);
NEGATE( aBuffer[ii].y );
}
}
break;
......@@ -312,77 +456,149 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector
case AMP_LINE_CENTER:
{
wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
// Build poly:
pos.x -= size.x/2;
pos.y -= size.y/2; // Lower left
aBuffer.push_back(pos);
pos.y += size.y; // Upper left
aBuffer.push_back(pos);
pos.x += size.x; // Upper right
aBuffer.push_back(pos);
pos.y -= size.y; // lower right
aBuffer.push_back(pos);
pos.x -= size.x / 2;
pos.y -= size.y / 2; // Lower left
aBuffer.push_back( pos );
pos.y += size.y; // Upper left
aBuffer.push_back( pos );
pos.x += size.x; // Upper right
aBuffer.push_back( pos );
pos.y -= size.y; // lower right
aBuffer.push_back( pos );
}
break;
case AMP_LINE_LOWER_LEFT:
{
wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue(
tool ), aUnitsMetric );
// Build poly:
NEGATE(lowerLeft.y);
aBuffer.push_back(lowerLeft);
NEGATE( lowerLeft.y );
aBuffer.push_back( lowerLeft );
lowerLeft.y += size.y; // Upper left
aBuffer.push_back(lowerLeft);
aBuffer.push_back( lowerLeft );
lowerLeft.x += size.x; // Upper right
aBuffer.push_back(lowerLeft);
aBuffer.push_back( lowerLeft );
lowerLeft.y -= size.y; // lower right
aBuffer.push_back(lowerLeft);
aBuffer.push_back( lowerLeft );
// Negate y coordinates:
for( unsigned ii = 0; ii < aBuffer.size(); ii++ )
NEGATE(aBuffer[ii].y);
NEGATE( aBuffer[ii].y );
}
break;
case AMP_THERMAL:
{
int outerDiam = scale( this->params[2].GetValue( tool ), aUnitsMetric );
int innerDiam = scale( this->params[3].GetValue( tool ), aUnitsMetric );
// Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
// rotated by 90, 180 and 270 deg.
// params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
int outerRadius = scale( params[2].GetValue( tool ), aUnitsMetric ) / 2;
int innerRadius = scale( params[3].GetValue( tool ), aUnitsMetric ) / 2;
int halfthickness = scale( params[4].GetValue( tool ), aUnitsMetric ) / 2;
int angle_start = wxRound( asin(
(double) halfthickness / innerRadius ) * 1800 / M_PI );
// Draw shape in the first cadrant (X and Y > 0)
wxPoint pos, startpos;
// Inner arc
startpos.x = innerRadius;
int angle_end = 900 - angle_start;
int angle;
for( angle = angle_start; angle < angle_end; angle += 100 )
{
pos = startpos;
RotatePoint( &pos, angle );
aBuffer.push_back( pos );
}
// Last point
pos = startpos;
RotatePoint( &pos, angle_end );
aBuffer.push_back( pos );
// outer arc
startpos.x = outerRadius;
startpos.y = 0;
angle_start = wxRound( asin( (double) halfthickness / outerRadius ) * 1800 / M_PI );
angle_end = 900 - angle_start;
// First point, near Y axis, outer arc
for( angle = angle_end; angle > angle_start; angle -= 100 )
{
pos = startpos;
RotatePoint( &pos, angle );
aBuffer.push_back( pos );
}
// last point
pos = startpos;
RotatePoint( &pos, angle_start );
aBuffer.push_back( pos );
aBuffer.push_back( aBuffer[0] ); // Close poly
}
break;
case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon
// because circles can be drawn easily
{
int crossHairThickness = scale( this->params[6].GetValue( tool ), aUnitsMetric );
int crossHairLength = scale( this->params[7].GetValue( tool ), aUnitsMetric );
int crossHairThickness = scale( params[6].GetValue( tool ), aUnitsMetric );
int crossHairLength = scale( params[7].GetValue( tool ), aUnitsMetric );
// Create cross. First create 1/4 of the shape.
// Others point are the same, totated by 90, 180 and 270 deg
wxPoint pos(crossHairThickness/2, crossHairLength/2);
aBuffer.push_back(pos);
pos.y = crossHairThickness/2;
aBuffer.push_back(pos);
pos.x = -crossHairLength/2;
aBuffer.push_back(pos);
pos.y = -crossHairThickness/2;
aBuffer.push_back(pos);
// Copy these 4 points, rotated by 90, 180 and 270 deg
wxPoint pos( crossHairThickness / 2, crossHairLength / 2 );
aBuffer.push_back( pos );
pos.y = crossHairThickness / 2;
aBuffer.push_back( pos );
pos.x = -crossHairLength / 2;
aBuffer.push_back( pos );
pos.y = -crossHairThickness / 2;
aBuffer.push_back( pos );
// Copy the 4 shape, rotated by 90, 180 and 270 deg
for( int jj = 900; jj <= 2700; jj += 900 )
{
for( int ii = 0; ii < 4; ii++ )
{
pos = aBuffer[ii];
RotatePoint(&pos,jj);
aBuffer.push_back(pos);
RotatePoint( &pos, jj );
aBuffer.push_back( pos );
}
}
}
break;
case AMP_UNKNOWN:
case AMP_OUTLINE:
case AMP_POLYGON:
// already is a polygon. Do nothing
break;
case AMP_POLYGON: // Creates a regular polygon
{
int vertexcount = wxRound( params[1].GetValue( tool ) );
int radius = scale( params[4].GetValue( tool ), aUnitsMetric ) / 2;
// rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
if( vertexcount < 3 )
vertexcount = 3;
if( vertexcount > 10 )
vertexcount = 10;
for( int ii = 0; ii <= vertexcount; ii++ )
{
wxPoint pos( radius, 0);
RotatePoint( &pos, ii * 3600 / vertexcount );
aBuffer.push_back( pos );
}
}
break;
case AMP_UNKNOWN:
case AMP_EOF:
break;
}
......@@ -394,15 +610,16 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector
* When an item is flashed, this is the shape of the item
*/
void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent,
EDA_Rect* aClipBox,
wxDC* aDC,
int aColor,
wxPoint aShapePos,
bool aFilledShape )
EDA_Rect* aClipBox, wxDC* aDC,
int aColor, int aAltColor,
wxPoint aShapePos, bool aFilledShape )
{
for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
prim_macro != primitives.end(); ++prim_macro )
{
prim_macro->DrawBasicShape( aParent, aClipBox, aDC, aColor, aShapePos, aFilledShape );
prim_macro->DrawBasicShape( aParent, aClipBox, aDC,
aColor, aAltColor,
aShapePos,
aFilledShape );
}
}
......@@ -84,21 +84,37 @@ public:
* returns the first parameter in integer form. Some but not all primitives
* use the first parameter as an exposure control.
*/
int GetExposure() const
{
// No D_CODE* for GetValue()
wxASSERT( params.size() && params[0].IsImmediate() );
return (int) params[0].GetValue( NULL );
}
int GetExposure() const;
/**
* Function mapExposure
* translates the first parameter from an aperture macro into a current
* exposure setting.
* @param aParent = a GERBER_DRAW_ITEM that handle:
* ** m_Exposure A dynamic setting which can change throughout the
* reading of the gerber file, and it indicates whether the current tool
* is lit or not.
* ** m_ImageNegative A dynamic setting which can change throughout the reading
* of the gerber file, and it indicates whether the current D codes are to
* be interpreted as erasures or not.
* @return true to draw with current color, false to draw with alt color (erase)
*/
bool mapExposure( GERBER_DRAW_ITEM* aParent );
/* Draw functions: */
/** function DrawBasicShape
* Draw the primitive shape for flashed items.
* @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn
* @param aClipBox = DC clip box (NULL is no clip)
* @param aDC = device context
* @param aColor = the normal color to use
* @param aAltColor = the color used to draw with "reverse" exposure mode (used in aperture macros only)
* @param aShapePos = the actual shape position
* @param aFilledShape = true to draw in filled mode, false to draw in skecth mode
*/
void DrawBasicShape( GERBER_DRAW_ITEM* aParent, EDA_Rect* aClipBox, wxDC* aDC,
int aColor, wxPoint aShapePos, bool aFilledShape );
int aColor, int aAltColor, wxPoint aShapePos, bool aFilledShape );
private:
......@@ -126,9 +142,16 @@ struct APERTURE_MACRO
/** function DrawApertureMacroShape
* Draw the primitive shape for flashed items.
* When an item is flashed, this is the shape of the item
* @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn
* @param aClipBox = DC clip box (NULL is no clip)
* @param aDC = device context
* @param aColor = the normal color to use
* @param aAltColor = the color used to draw with "reverse" exposure mode (used in aperture macros only)
* @param aShapePos = the actual shape position
* @param aFilledShape = true to draw in filled mode, false to draw in skecth mode
*/
void DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent, EDA_Rect* aClipBox, wxDC* aDC,
int aColor, wxPoint aShapePos, bool aFilledShape );
int aColor, int aAltColor, wxPoint aShapePos, bool aFilledShape );
};
......
......@@ -50,6 +50,8 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( BOARD_ITEM* aParent ) :
m_Flashed = false;
m_DCode = 0;
m_UnitsMetric = false;
m_ImageNegative = false;
m_LayerNegative = false;
}
......@@ -72,6 +74,9 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) :
m_DCode = aSource.m_DCode;
m_PolyCorners = aSource.m_PolyCorners;
m_UnitsMetric = aSource.m_UnitsMetric;
m_ImageNegative = aSource.m_ImageNegative;
m_LayerNegative = aSource.m_LayerNegative;
}
......@@ -183,7 +188,7 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
/*********************************************************************/
{
static D_CODE dummyD_CODE( 0 ); // used when a D_CODE is not found. default D_CODE to draw a flashed item
int color;
int color, alt_color;
bool isFilled;
int radius;
int halfPenWidth;
......@@ -194,26 +199,26 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
if( d_codeDescr == NULL )
d_codeDescr = &dummyD_CODE;
if( m_Flags & DRAW_ERASED ) // draw in background color ("negative" color)
if( brd->IsLayerVisible( GetLayer() ) == false )
return;
color = brd->GetLayerColor( GetLayer() );
if( aDrawMode & GR_SURBRILL )
{
color = g_DrawBgColor;
if( aDrawMode & GR_AND )
color &= ~HIGHT_LIGHT_FLAG;
else
color |= HIGHT_LIGHT_FLAG;
}
else
{
if( brd->IsLayerVisible( GetLayer() ) == false )
return;
if( color & HIGHT_LIGHT_FLAG )
color = ColorRefs[color & MASKCOLOR].m_LightColor;
color = brd->GetLayerColor( GetLayer() );
alt_color = g_DrawBgColor ;
if( aDrawMode & GR_SURBRILL )
{
if( aDrawMode & GR_AND )
color &= ~HIGHT_LIGHT_FLAG;
else
color |= HIGHT_LIGHT_FLAG;
}
if( color & HIGHT_LIGHT_FLAG )
color = ColorRefs[color & MASKCOLOR].m_LightColor;
if( m_Flags & DRAW_ERASED ) // draw in background color ("negative" color)
{
EXCHG(color, alt_color);
}
GRSetDrawMode( aDC, aDrawMode );
......@@ -272,7 +277,7 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
case GBR_SPOT_POLY:
case GBR_SPOT_MACRO:
isFilled = DisplayOpt.DisplayPadFill ? true : false;
d_codeDescr->DrawFlashedShape( this, &aPanel->m_ClipBox, aDC, color,
d_codeDescr->DrawFlashedShape( this, &aPanel->m_ClipBox, aDC, color, alt_color,
m_Start, isFilled );
break;
......
......@@ -74,6 +74,8 @@ public:
// 0 for items that do not use DCodes (polygons)
// or when unknown and normal values are 10 to 999
// values 0 to 9 can be used for special purposes
bool m_ImageNegative; // true = item in negative image
bool m_LayerNegative; // TRUE = item in negative Layer
public:
GERBER_DRAW_ITEM( BOARD_ITEM* aParent );
......
......@@ -293,7 +293,7 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
* When an item is flashed, the DCode shape is the shape of the item
*/
void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent,
EDA_Rect* aClipBox, wxDC* aDC, int aColor,
EDA_Rect* aClipBox, wxDC* aDC, int aColor, int aAltColor,
wxPoint aShapePos, bool aFilledShape )
{
int radius;
......@@ -301,7 +301,8 @@ void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent,
switch( m_Shape )
{
case APT_MACRO:
GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor, aShapePos, aFilledShape);
GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor, aAltColor,
aShapePos, aFilledShape);
break;
case APT_CIRCLE:
......
......@@ -193,9 +193,15 @@ public:
/** function DrawFlashedShape
* Draw the dcode shape for flashed items.
* When an item is flashed, the DCode shape is the shape of the item
* @param aClipBox = DC clip box (NULL is no clip)
* @param aDC = device context
* @param aColor = the normal color to use
* @param aAltColor = the color used to draw with "reverse" exposure mode (used in aperture macros only)
* @param aFilled = true to draw in filled mode, false to draw in skecth mode
* @param aPosition = the actual shape position
*/
void DrawFlashedShape( GERBER_DRAW_ITEM* aParent,
EDA_Rect* aClipBox, wxDC* aDC, int aColor,
EDA_Rect* aClipBox, wxDC* aDC, int aColor, int aAltColor,
wxPoint aShapePos, bool aFilledShape );
/** function DrawFlashedPolygon
......@@ -203,7 +209,12 @@ public:
* Draw some Apertures shapes when they are defined as filled polygons.
* APT_POLYGON is always a polygon, but some complex shapes are also converted to
* polygons (shapes with holes, some rotated shapes)
*/
* @param aClipBox = DC clip box (NULL is no clip)
* @param aDC = device context
* @param aColor = the normal color to use
* @param aFilled = true to draw in filled mode, false to draw in skecth mode
* @param aPosition = the actual shape position
*/
void DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
bool aFilled, const wxPoint& aPosition );
......
G04 Verification of all aperture macros *
G04 Handcoded by Stefan Petersen *
%MOIN*%
%FSLAX23Y23*%
%OFA0.0000B0.0000*%
G90*
%AMCIRCLE*
1,1,0.5,0,0*
%
%AMVECTOR*
2,1,0.3,0,0,1,1,-15*
%
%AMLINE*
21,1,0.3,0.05,0,0,-135*
%
%AMLINE2*
22,1,0.8,0.5,0,0,-45*
%
%AMOUTLINE*
4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25*
%
%AMPOLYGON*
5,1,5,0,0,0.5,25*
%
%AMMOIRE*
6,0,0,1.0,0.1,0.4,2,0.01,1,20*
%
%AMTHERMAL*
7,0,0,1.0,0.3,0.04,-13*
%
%ADD10C,0.0650*%
%ADD11CIRCLE*%
%ADD12VECTOR*%
%ADD13LINE*%
%ADD14LINE2*%
%ADD15OUTLINE*%
%ADD16POLYGON*%
%ADD18MOIRE*%
%ADD19THERMAL*%
G04 Outline*
X0Y0D02*
G54D10*
X0Y0D01*
X10000D01*
Y10000D01*
X0D01*
Y0D01*
G04 Dots *
X2000Y5000D03*
X3000D03*
X4000D03*
X5000D03*
X6000D03*
X7000D03*
X8000D03*
X9000D03*
Y6200X9000D03*
G04 Draw circle*
G54D11*
X2000Y5000D03*
G04 Draw line vector *
G54D12*
X3000D03*
G04 Draw line center *
G54D13*
X4000D03*
G04 Draw line lower left *
G54D14*
X5000D03*
G04 Draw outline *
G54D15*
X6000D03*
G04 Draw polygon 1 *
G54D16*
X7000D03*
G04 Draw Moire *
G54D18*
X9000D03*
G04 Draw Thermal *
G54D19*
Y6200X9000D03*
M02*
......@@ -76,123 +76,68 @@ static wxPoint LastPosition;
/**
* Function fillCircularGBRITEM
* initializes a given GBRITEM so that it can draw a circle which is not filled
* and
* has a given pen width (\a aPenWidth ).
*
* @param aGbrItem The GBRITEM to fill in.
* @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the flash
* @param aDiameter The diameter of the round flash
* @param aPenWidth The width of the pen used to draw the circle's
* circumference.
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
static void fillCircularGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
int aDiameter,
int aPenWidth,
bool isDark )
{
aGbrItem->m_Shape = GBR_CIRCLE;
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aPenWidth;
aGbrItem->SetLayer( aLayer );
aGbrItem->m_DCode = Dcode_index;
// When drawing a GBRITEM with shape GBR_CIRCLE, the hypotenuse (i.e. distance)
// between the Start and End points gives the radius of the circle.
aGbrItem->m_Start = aGbrItem->m_End = aPos;
aGbrItem->m_End.x += max( 0, (aDiameter + 1) / 2 );
NEGATE( aGbrItem->m_Start.y );
NEGATE( aGbrItem->m_End.y );
if( !isDark )
{
aGbrItem->m_Flags |= DRAW_ERASED;
}
}
/**
* Function fillRoundFlashGBRITEM
* Function fillFlashedGBRITEM
* initializes a given GBRITEM so that it can draw a circle which is filled and
* has no pen border.
*
* @param aGbrItem The GBRITEM to fill in.
* @param aAperture the associated type of aperture
* @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the flash
* @param aDiameter The diameter of the round flash
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
* @param aSize The diameter of the round flash
* @param aLayerNegative = true if the current layer is negative
* @param aImageNegative = true if the current image is negative
*/
static void fillRoundFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
int aDiameter,
bool isDark )
static void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
APERTURE_T aAperture,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
wxSize aSize,
bool aLayerNegative,
bool aImageNegative )
{
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aDiameter;
aGbrItem->m_Size = aSize;
aGbrItem->m_Start = aPos;
NEGATE( aGbrItem->m_Start.y );
aGbrItem->m_End = aGbrItem->m_Start;
aGbrItem->m_End = aGbrItem->m_Start;
aGbrItem->m_DCode = Dcode_index;
aGbrItem->m_Shape = GBR_SPOT_CIRCLE;
aGbrItem->m_LayerNegative = aLayerNegative;
aGbrItem->m_ImageNegative = aImageNegative;
aGbrItem->m_Flashed = true;
if( !isDark )
switch( aAperture )
{
aGbrItem->m_Flags |= DRAW_ERASED;
}
}
case APT_POLYGON: // flashed regular polygon
aGbrItem->m_Shape = GBR_SPOT_POLY;
break;
case APT_LINE: // Should not be used.
case APT_CIRCLE:
aGbrItem->m_Shape = GBR_SPOT_CIRCLE;
aGbrItem->m_Size.y = aGbrItem->m_Size.x;
break;
/**
* Function fillOvalOrRectFlashGBRITEM
* initializes a given GBRITEM so that it can draw an oval or rectangular
* filled rectangle.
*
* @param aGbrItem The GERBER_DRAW_ITEM to fill in.
* @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the rectangle
* @param aSize The size of the flash
* @param aShape What type of flash, GBR_SPOT_OVALE or GBR_SPOT_RECT
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
static void fillOvalOrRectFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
const wxSize& aSize,
int aShape,
bool isDark )
{
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Flashed = true;
case APT_OVAL:
aGbrItem->m_Shape = GBR_SPOT_OVAL;
break;
aGbrItem->m_Size = aSize;
case APT_RECT:
aGbrItem->m_Shape = GBR_SPOT_RECT;
break;
aGbrItem->m_Start = aPos;
NEGATE( aGbrItem->m_Start.y );
aGbrItem->m_End = aGbrItem->m_Start;
case APT_MACRO:
aGbrItem->m_Shape = GBR_SPOT_MACRO;
break;
}
aGbrItem->m_DCode = Dcode_index;
aGbrItem->m_Shape = aShape;
bool isDark = !(aGbrItem->m_LayerNegative ^ aGbrItem->m_ImageNegative);
/* isDark is true if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
if( !isDark )
{
aGbrItem->m_Flags |= DRAW_ERASED;
......@@ -209,9 +154,8 @@ static void fillOvalOrRectFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the flash
* @param aDiameter The diameter of the round flash
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
* @param aLayerNegative = true if the current layer is negative
* @param aImageNegative = true if the current image is negative
*/
static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
......@@ -219,7 +163,8 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
const wxPoint& aStart,
const wxPoint& aEnd,
int aWidth,
bool isDark )
bool aLayerNegative,
bool aImageNegative )
{
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Flashed = false;
......@@ -233,7 +178,15 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
NEGATE( aGbrItem->m_End.y );
aGbrItem->m_DCode = Dcode_index;
aGbrItem->m_LayerNegative = aLayerNegative;
aGbrItem->m_ImageNegative = aImageNegative;
bool isDark = !(aGbrItem->m_LayerNegative ^ aGbrItem->m_ImageNegative);
/* isDark is true if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
if( !isDark )
{
aGbrItem->m_Flags |= DRAW_ERASED;
......@@ -267,20 +220,21 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* same quadrant.
* @param aDiameter The diameter of the round flash
* @param aWidth is the pen width.
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
* @param aLayerNegative = true if the current layer is negative
* @param aImageNegative = true if the current image is negative
*/
static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aLayer,
const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& rel_center, int aWidth,
bool clockwise, bool multiquadrant, bool isDark )
bool clockwise, bool multiquadrant,
bool aLayerNegative,
bool aImageNegative )
{
wxPoint center, delta;
aGbrItem->m_Shape = GBR_ARC;
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth;
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth;
aGbrItem->m_Flashed = false;
if( multiquadrant )
......@@ -347,6 +301,15 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL
NEGATE( aGbrItem->m_End.y );
NEGATE( aGbrItem->m_ArcCentre.y );
aGbrItem->m_LayerNegative = aLayerNegative;
aGbrItem->m_ImageNegative = aImageNegative;
bool isDark = !(aGbrItem->m_LayerNegative ^ aGbrItem->m_ImageNegative);
/* isDark is true if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
if( !isDark )
{
aGbrItem->m_Flags |= DRAW_ERASED;
......@@ -379,23 +342,38 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL
* same quadrant.
* @param aDiameter The diameter of the round flash
* @param aWidth is the pen width.
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
* @param aLayerNegative = true if the current layer is negative
* @param aImageNegative = true if the current image is negative
*/
static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGrbrItem,
static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGbrItem,
const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& rel_center,
bool clockwise, bool multiquadrant, bool isDark )
bool clockwise, bool multiquadrant,
bool aLayerNegative,
bool aImageNegative )
{
/* in order to calculate arc parameters, we use fillArcGBRITEM
* so we muse create a dummy track and use its geometric parameters
*/
static GERBER_DRAW_ITEM dummyGbrItem( NULL );
aGbrItem->m_LayerNegative = aLayerNegative;
aGbrItem->m_ImageNegative = aImageNegative;
bool isDark = !(aGbrItem->m_LayerNegative ^ aGbrItem->m_ImageNegative);
/* isDark is true if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
if( !isDark )
{
aGbrItem->m_Flags |= DRAW_ERASED;
}
fillArcGBRITEM( &dummyGbrItem, 0, 0,
aStart, aEnd, rel_center, 0,
clockwise, multiquadrant, isDark );
clockwise, multiquadrant, aLayerNegative, aImageNegative );
// dummyTrack has right geometric parameters, and has its Y coordinates negated (to match the pcbnew Y axis).
// Approximate arc by 36 segments per 360 degree
......@@ -457,14 +435,10 @@ static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGrbrItem,
// D( printf( " >> Add arc %d rot %d, edge poly item %d,%d to %d,%d\n",
// ii, rot, start_arc.x, start_arc.y,end_arc.x, end_arc.y ); )
if( aGrbrItem->m_PolyCorners.size() == 0 )
aGrbrItem->m_PolyCorners.push_back( start_arc + center );
aGrbrItem->m_PolyCorners.push_back( end_arc + center );
if( aGbrItem->m_PolyCorners.size() == 0 )
aGbrItem->m_PolyCorners.push_back( start_arc + center );
aGbrItem->m_PolyCorners.push_back( end_arc + center );
if( !isDark )
{
aGrbrItem->m_Flags |= DRAW_ERASED;
}
start_arc = end_arc;
}
}
......@@ -537,10 +511,11 @@ wxPoint GERBER::ReadXYCoord( char*& Text )
if( fmt_scale < 0 || fmt_scale > 9 )
fmt_scale = 4;
double scale_list[10] =
{ 10000.0, 1000.0, 100.0, 10.0,
1,
0.1, 0.01, 0.001, 0.0001, 0.00001
};
{
10000.0, 1000.0, 100.0, 10.0,
1,
0.1, 0.01, 0.001, 0.0001,0.00001
};
real_scale = scale_list[fmt_scale];
if( m_GerbMetric )
......@@ -635,9 +610,10 @@ wxPoint GERBER::ReadIJCoord( char*& Text )
fmt_scale = 4; // select scale 1.0
double scale_list[10] =
{ 10000.0, 1000.0, 100.0, 10.0,
{
10000.0, 1000.0, 100.0, 10.0,
1,
0.1, 0.01, 0.001, 0.0001, 0.00001
0.1, 0.01, 0.001, 0.0001,0.00001
};
real_scale = scale_list[fmt_scale];
......@@ -707,7 +683,7 @@ int GERBER::ReturnDCodeNumber( char*& Text )
bool GERBER::Execute_G_Command( char*& text, int G_commande )
{
D( printf( "%22s: G_CODE<%d>\n", __func__, G_commande ); )
// D( printf( "%22s: G_CODE<%d>\n", __func__, G_commande ); )
switch( G_commande )
{
......@@ -832,49 +808,12 @@ int scale( double aCoord, bool isMetric )
*/
wxPoint mapPt( double x, double y, bool isMetric )
{
wxPoint ret( scale( x, isMetric ),
scale( y, isMetric ) );
wxPoint ret( scale( x, isMetric ), scale( y, isMetric ) );
return ret;
}
/**
* Function mapExposure
* translates the first parameter from an aperture macro into a current
* exposure
* setting.
* @param curExposure A dynamic setting which can change throughout the
* reading of the gerber file, and it indicates whether the current tool
* is lit or not.
* @param isNegative A dynamic setting which can change throughout the reading
* of
* the gerber file, and it indicates whether the current D codes are to
* be interpreted as erasures or not.
*/
static bool mapExposure( int param1, bool curExposure, bool isNegative )
{
bool exposure;
switch( param1 )
{
case 0:
exposure = false;
break;
default:
case 1:
exposure = true;
break;
case 2:
exposure = !curExposure;
}
return exposure ^ isNegative;
}
bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int D_commande )
{
wxSize size( 15, 15 );
......@@ -889,7 +828,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int
D_CODE* tool = NULL;
wxString msg;
D( printf( "%22s: D_CODE<%d>\n", __func__, D_commande ); )
// D( printf( "%22s: D_CODE<%d>\n", __func__, D_commande ); )
if( D_commande >= FIRST_DCODE ) // This is a "Set tool" command
{
......@@ -923,7 +862,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int
pcb->m_Drawings.Append( gbritem );
gbritem->m_Shape = GBR_POLYGON;
gbritem->SetLayer( activeLayer );
gbritem->m_Flashed = false;
gbritem->m_Flashed = false;
gbritem->m_UnitsMetric = m_GerbMetric;
}
......@@ -932,21 +871,20 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int
case GERB_INTERPOL_ARC_NEG:
case GERB_INTERPOL_ARC_POS:
gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() );
D( printf( "Add arc poly %d,%d to %d,%d fill %d interpol %d 360_enb %d\n",
m_PreviousPos.x, m_PreviousPos.y, m_CurrentPos.x,
m_CurrentPos.y, m_PolygonFillModeState, m_Iterpolation, m_360Arc_enbl ); )
// D( printf( "Add arc poly %d,%d to %d,%d fill %d interpol %d 360_enb %d\n",
// m_PreviousPos.x, m_PreviousPos.y, m_CurrentPos.x,
// m_CurrentPos.y, m_PolygonFillModeState, m_Iterpolation, m_360Arc_enbl ); )
fillArcPOLY( pcb, gbritem, m_PreviousPos,
m_CurrentPos, m_IJPos,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl,
!(m_LayerNegative ^ m_ImageNegative) );
false : true, m_360Arc_enbl, m_LayerNegative, m_ImageNegative );
break;
default:
gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() );
D( printf( "Add poly edge %d,%d to %d,%d fill %d\n",
m_PreviousPos.x, m_PreviousPos.y,
m_CurrentPos.x, m_CurrentPos.y, m_Iterpolation ); )
// D( printf( "Add poly edge %d,%d to %d,%d fill %d\n",
// m_PreviousPos.x, m_PreviousPos.y,
// m_CurrentPos.x, m_CurrentPos.y, m_Iterpolation ); )
gbritem->m_Start = m_PreviousPos; // m_Start is used as temporary storage
NEGATE( gbritem->m_Start.y );
......@@ -962,7 +900,6 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int
{
if( m_LayerNegative ^ m_ImageNegative )
gbritem->m_Flags |= DRAW_ERASED;
D( printf( "\nm_Flags=0x%08X\n", gbritem->m_Flags ); )
}
break;
}
......@@ -1002,10 +939,9 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int
gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
// D( printf( "R:%p\n", gbritem ); )
fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) );
m_CurrentPos, size.x, m_LayerNegative, m_ImageNegative );
break;
case GERB_INTERPOL_LINEAR_01X:
......@@ -1019,12 +955,12 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int
gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
// D( printf( "R:%p\n", gbritem ); )
fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, m_IJPos, size.x,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl,
!(m_LayerNegative ^ m_ImageNegative) );
m_LayerNegative, m_ImageNegative );
break;
default:
......@@ -1051,288 +987,13 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int
aperture = tool->m_Shape;
}
switch( aperture )
{
case APT_POLYGON: // flashed regular polygon
case APT_CIRCLE:
gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) );
if( aperture == APT_POLYGON )
gbritem->m_Shape = GBR_SPOT_POLY;
break;
case APT_OVAL:
case APT_RECT:
gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
m_CurrentPos, size,
( aperture == APT_RECT ) ?
GBR_SPOT_RECT : GBR_SPOT_OVAL,
!(m_LayerNegative ^ m_ImageNegative) );
break;
case APT_MACRO:
{
APERTURE_MACRO* macro = tool->GetMacro();
wxASSERT( macro );
#if 1
gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem );
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) );
gbritem->m_Shape = GBR_SPOT_MACRO;
#else
// split the macro primitives up into multiple normal GBRITEM
// elements
for( AM_PRIMITIVES::iterator p = macro->primitives.begin();
p!=macro->primitives.end();
++p )
{
bool exposure;
wxPoint curPos = m_CurrentPos;
switch( p->primitive_id )
{
case AMP_CIRCLE:
{
exposure = mapExposure( p->GetExposure(), m_Exposure,
m_ImageNegative );
curPos += mapPt( p->params[2].GetValue( tool ),
p->params[3].GetValue( tool ),
m_GerbMetric );
int diameter = scale( p->params[1].GetValue( tool ),
m_GerbMetric );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, diameter, exposure );
}
break;
case AMP_LINE2:
case AMP_LINE20:
{
exposure = mapExposure(
p->GetExposure(), m_Exposure, m_ImageNegative );
int width = scale( p->params[1].GetValue( tool ),
m_GerbMetric );
wxPoint start = mapPt( p->params[2].GetValue( tool ),
p->params[3].GetValue( tool ),
m_GerbMetric );
wxPoint end = mapPt( p->params[4].GetValue( tool ),
p->params[5].GetValue( tool ),
m_GerbMetric );
if( start.x == end.x )
{
size.x = width;
size.y = ABS( end.y - start.y ) + 1;
}
else
{
size.x = ABS( end.x - start.x ) + 1;
size.y = width;
}
wxPoint midPoint( ( start.x + end.x ) / 2,
( start.y + end.y ) / 2 );
curPos += midPoint;
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, size, GBR_SPOT_RECT,
exposure );
}
break;
case AMP_LINE_CENTER:
{
exposure = mapExposure( p->GetExposure(), m_Exposure,
m_ImageNegative );
wxPoint msize = mapPt( p->params[1].GetValue( tool ),
p->params[2].GetValue( tool ),
m_GerbMetric );
size.x = msize.x;
size.y = msize.y;
curPos += mapPt( p->params[3].GetValue( tool ),
p->params[4].GetValue( tool ),
m_GerbMetric );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, size, GBR_SPOT_RECT,
exposure );
}
break;
case AMP_LINE_LOWER_LEFT:
{
exposure = mapExposure(
p->GetExposure(), m_Exposure, m_ImageNegative );
wxPoint msize = mapPt( p->params[1].GetValue( tool ),
p->params[2].GetValue( tool ),
m_GerbMetric );
size.x = msize.x;
size.y = msize.y;
wxPoint lowerLeft = mapPt( p->params[3].GetValue( tool ),
p->params[4].GetValue( tool ),
m_GerbMetric );
curPos += lowerLeft;
// need the middle, so adjust from the lower left
curPos.y += size.y / 2;
curPos.x += size.x / 2;
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, size, GBR_SPOT_RECT,
exposure );
}
break;
case AMP_THERMAL:
{
int outerDiam = scale( p->params[2].GetValue( tool ),
m_GerbMetric );
int innerDiam = scale( p->params[3].GetValue( tool ),
m_GerbMetric );
curPos += mapPt( p->params[0].GetValue( tool ),
p->params[1].GetValue( tool ),
m_GerbMetric );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, outerDiam,
!( m_LayerNegative ^ m_ImageNegative ) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer, curPos,
innerDiam,
( m_LayerNegative ^ m_ImageNegative ) );
// @todo: draw the cross hairs, see page 23 of rs274
// spec. this might be done with two lines, thickness
// from params[4], and drawing
// darkness "(m_LayerNegative ^ m_ImageNegative)"
}
break;
case AMP_MOIRE:
{
curPos += mapPt( p->params[0].GetValue( tool ),
p->params[1].GetValue( tool ),
m_GerbMetric );
// e.g.: "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
int outerDiam = scale( p->params[2].GetValue( tool ),
m_GerbMetric );
int penThickness = scale( p->params[3].GetValue( tool ),
m_GerbMetric );
int gap = scale( p->params[4].GetValue( tool ),
m_GerbMetric );
int numCircles = (int) p->params[5].GetValue( tool );
int crossHairThickness =
scale( p->params[6].GetValue( tool ), m_GerbMetric );
int crossHairLength =
scale( p->params[7].GetValue( tool ), m_GerbMetric );
// ignore rotation, not supported
// adjust outerDiam by this on each nested circle
int diamAdjust = 2 * (gap + penThickness);
for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
{
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillCircularGBRITEM( gbritem, dcode, activeLayer,
curPos, outerDiam,
penThickness,
!( m_LayerNegative ^ m_ImageNegative ) );
}
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos,
wxSize( crossHairThickness,
crossHairLength ),
GBR_SPOT_RECT,
!( m_LayerNegative ^ m_ImageNegative ) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
// swap x and y in wxSize() for this one
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos,
wxSize( crossHairLength,
crossHairThickness ),
GBR_SPOT_RECT,
!( m_LayerNegative ^ m_ImageNegative ) );
}
break;
case AMP_OUTLINE:
#if defined(DEBUG)
{
int numPoints = (int) p->params[1].GetValue( tool );
printf( "AMP_OUTLINE:\n" );
printf( " exposure: %g\n", p->params[0].GetValue( tool ) );
printf( " # points: %d\n", numPoints );
// numPoints does not include the starting point, so add 1.
for( int i = 0; i<numPoints + 1; ++i )
{
printf( " [%d]: X=%g Y=%g\n", i,
p->params[i * 2 + 2 + 0].GetValue( tool ),
p->params[i * 2 + 2 + 1].GetValue( tool )
);
}
printf( " rotation: %g\n", p->params[numPoints * 2 + 4].GetValue( tool ) );
}
#endif
break;
case AMP_POLYGON:
case AMP_EOF:
default:
// not yet supported, waiting for you.
break;
}
}
#endif
}
break;
default:
break;
}
gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem );
// D( printf( "R:%p dcode %d layer %d\n", gbritem, dcode, activeLayer ); )
fillFlashedGBRITEM( gbritem, aperture,
dcode, activeLayer, m_CurrentPos,
size, m_LayerNegative, m_ImageNegative );
m_PreviousPos = m_CurrentPos;
break;
......
......@@ -173,8 +173,7 @@ bool GERBER::ExecuteRS274XCommand( int command,
double conv_scale = m_GerbMetric ? PCB_INTERNAL_UNIT /
25.4 : PCB_INTERNAL_UNIT;
D( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF,
command & 0xFF ); )
// D( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF, command & 0xFF ); )
switch( command )
{
......@@ -663,7 +662,7 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ],
break;
case AMP_POLYGON:
paramCount = 4;
paramCount = 6;
break;
case AMP_MOIRE:
......@@ -703,7 +702,8 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ],
if( i < paramCount ) // maybe some day we can throw an exception and
// track a line number
printf( "i=%d, insufficient parameters\n", i );
printf( "read macro descr type %d: read %d parameters, insufficient parameters\n",
prim.primitive_id, i );
// there are more parameters to read if this is an AMP_OUTLINE
if( prim.primitive_id == AMP_OUTLINE )
......
/* Bits characterizing cell */
#define HOLE (char)0x01 /* a conducting hole or obstacle */
#define CELL_is_MODULE (char)0x02 /* auto placement occupied by a module */
#define CELL_is_EDGE (char)0x20 /* Area and auto-placement: limiting cell
#define HOLE 0x01 /* a conducting hole or obstacle */
#define CELL_is_MODULE 0x02 /* auto placement occupied by a module */
#define CELL_is_EDGE 0x20 /* Area and auto-placement: limiting cell
* contour (Board, Zone) */
#define CELL_is_FRIEND (char)0x40 /* Area and auto-placement: cell part of the
#define CELL_is_FRIEND 0x40 /* Area and auto-placement: cell part of the
* net */
#define CELL_is_ZONE (char)0x80 /* Area and auto-placement: cell available */
#define CELL_is_ZONE 0x80 /* Area and auto-placement: cell available */
/* Bit masks for presence of obstacles to autorouting */
#define OCCUPE 1 /* Autorouting: obstacle tracks and vias. */
......
......@@ -65,7 +65,7 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( PLOTTER* plotter,
Plot_Edges_Modules( plotter, m_Pcb, masque_layer, trace_mode );
/* Plot pads (creates pads outlines, for pads on silkscreen layers) */
bool layersmask_plotpads = masque_layer;
int layersmask_plotpads = masque_layer;
// Calculate the mask layers of allowed layers for pads
if( !g_pcb_plot_options.PlotPadsOnSilkLayer )
layersmask_plotpads &= ~(SILKSCREEN_LAYER_BACK || SILKSCREEN_LAYER_FRONT);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment