Commit 3144853b authored by jean-pierre charras's avatar jean-pierre charras

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

finished Draw functions for aperture macros.  Now aperture macros are drawn correctly.  Known bug: aperture macros having parameters are incorrect: parameters are not read correctly. Work still in progress.
parents 98303013 bc0d79d5
...@@ -4,6 +4,14 @@ KiCad ChangeLog 2010 ...@@ -4,6 +4,14 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. 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> 2010-sept-28, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================ ================================================================================
++gerbview: ++gerbview:
......
...@@ -1163,6 +1163,9 @@ static bool IsGRSPolyDrawable( EDA_Rect* ClipBox, int n, wxPoint Points[] ) ...@@ -1163,6 +1163,9 @@ static bool IsGRSPolyDrawable( EDA_Rect* ClipBox, int n, wxPoint Points[] )
if( ! ClipBox ) if( ! ClipBox )
return true; return true;
if( n <= 0 )
return false;
int Xmin, Xmax, Ymin, Ymax; int Xmin, Xmax, Ymin, Ymax;
Xmin = Xmax = Points[0].x; Xmin = Xmax = Points[0].x;
......
...@@ -15,6 +15,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ...@@ -15,6 +15,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
### ###
set(GERBVIEW_SRCS set(GERBVIEW_SRCS
block.cpp block.cpp
class_aperture_macro.cpp
class_GERBER.cpp class_GERBER.cpp
class_gerber_draw_item.cpp class_gerber_draw_item.cpp
class_gerbview_layer_widget.cpp class_gerbview_layer_widget.cpp
......
/****************************/
/* class_aperture_macro.cpp */
/****************************/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "fctsys.h"
#include "common.h"
#include "macros.h"
#include "trigo.h"
#include "gerbview.h"
/** helper Function mapPt
* translates a point from the aperture macro coordinate system to our
* deci-mils coordinate system.
* @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
/**
* 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, 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;
int rotation;
if( mapExposure( aParent ) == false )
{
EXCHG(aColor, aAltColor);
}
switch( primitive_id )
{
case AMP_CIRCLE: // Circle, given diameter and position
{
/* 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 exposure
*/
curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), gerberMetric );
int radius = scale( params[1].GetValue( tool ), gerberMetric ) / 2;
if( !aFilledShape )
GRCircle( aClipBox, aDC, curPos.x, curPos.y, radius, aColor );
else
GRFilledCircle( aClipBox, aDC, curPos, radius, aColor );
}
break;
case AMP_LINE2:
case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
{
/* 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 exposure
*/
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
rotation = wxRound( params[6].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
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 );
}
break;
case AMP_LINE_CENTER:
{
/* 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 exposure
*/
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
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 );
}
break;
case AMP_LINE_LOWER_LEFT:
{
/* 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 exposure
*/
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
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 );
}
break;
case AMP_THERMAL:
{
/* Generated by an aperture macro declaration like:
* "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 center.x
*/
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:
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++ )
{
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 );
}
}
break;
case AMP_MOIRE: // A cross hair with n concentric circles
{
curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
gerberMetric );
/* Generated by an aperture macro declaration like:
* "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
* 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 penThickness = scale( params[3].GetValue( tool ), gerberMetric );
int gap = scale( params[4].GetValue( tool ), gerberMetric );
int numCircles = wxRound( params[5].GetValue( tool ) );
// adjust outerDiam by this on each nested circle
int diamAdjust = (gap + penThickness); //*2; //Should we use * 2 ?
for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
{
if( outerDiam <= 0 )
break;
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 );
}
else // Filled mode
{
GRCircle( aClipBox, aDC, curPos.x, curPos.y,
(outerDiam - penThickness) / 2, penThickness, aColor );
}
}
// Draw the cross:
ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
// shape rotation:
rotation = wxRound( params[8].GetValue( tool ) * 10.0 );
if( rotation )
{
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
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 );
}
break;
case AMP_OUTLINE:
{
/* 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++ )
{
NEGATE(polybuffer[ii].y);
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 );
}
break;
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;
}
GRClosedPoly( aClipBox, aDC,
polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
break;
case AMP_EOF:
// 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;
}
}
/** function ConvertShapeToPolygon (virtual)
* convert a shape to an equivalent polygon.
* Arcs and circles are approximated by segments
* Useful when a shape is not a graphic primitive (shape with hole,
* rotated shape ... ) and cannot be easily drawn.
* note for some schapes conbining circles and solid lines (rectangles), only rectangles are converted
* 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 )
{
D_CODE* tool = aParent->GetDcodeDescr();
switch( primitive_id )
{
case AMP_CIRCLE: // Circle, currently convertion not needed
break;
case AMP_LINE2:
case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
{
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 ) );
// 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 );
// Rotate rectangle and move it to the actual start point
int angle = wxRound( atan2( delta.y, delta.x ) * 1800.0 / M_PI );
for( unsigned ii = 0; ii < 4; ii++ )
{
RotatePoint( &aBuffer[ii], -angle );
aBuffer[ii] += start;
NEGATE( aBuffer[ii].y );
}
}
break;
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 );
// 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 );
}
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 );
// Build poly:
NEGATE( lowerLeft.y );
aBuffer.push_back( lowerLeft );
lowerLeft.y += size.y; // Upper left
aBuffer.push_back( lowerLeft );
lowerLeft.x += size.x; // Upper right
aBuffer.push_back( lowerLeft );
lowerLeft.y -= size.y; // lower right
aBuffer.push_back( lowerLeft );
// Negate y coordinates:
for( unsigned ii = 0; ii < aBuffer.size(); ii++ )
NEGATE( aBuffer[ii].y );
}
break;
case AMP_THERMAL:
{
// 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( 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 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 );
}
}
}
break;
case AMP_OUTLINE:
// 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;
}
}
/** function DrawApertureMacroShape
* Draw the primitive shape for flashed items.
* 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, 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, aAltColor,
aShapePos,
aFilledShape );
}
}
/**************************/
/* class_aperture_macro.h */
/**************************/
#ifndef _APERTURE_MACRO_H_
#define _APERTURE_MACRO_H_
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <vector>
#include <set>
#include "base_struct.h"
/**
* Enum AM_PRIMITIVE_ID
* is the set of all "aperture macro primitives" (primitive numbers). See
* Table 3 in http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
* aperture macro primitives are basic shapes which can be combined to create a complex shape
* This complex shape is flashed.
*/
enum AM_PRIMITIVE_ID {
AMP_UNKNOWN = 0, // A value for uninitialized AM_PRIMITIVE.
AMP_CIRCLE = 1, // Circle. (diameter and position)
AMP_LINE2 = 2, // Line with rectangle ends. (Width, start and end pos + rotation)
AMP_LINE20 = 20, // Same as AMP_LINE2
AMP_LINE_CENTER = 21, // Rectangle. (height, width and center pos + rotation)
AMP_LINE_LOWER_LEFT = 22, // Rectangle. (height, width and left bottom corner pos + rotation)
AMP_EOF = 3, // End Of File marquer: not really a shape
AMP_OUTLINE = 4, // Free polyline (n corners + rotation)
AMP_POLYGON = 5, // Closed regular polygon(diameter, number of vertices (3 to 10), rotation)
AMP_MOIRE = 6, // A cross hair with n concentric circles + rotation
AMP_THERMAL = 7, // Thermal shape (pos, outer and inner diameter, cross hair thickness + rotation)
};
/**
* Struct AM_PRIMITIVE
* holds an aperture macro primitive as given in Table 3 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/
class AM_PRIMITIVE
{
public:
AM_PRIMITIVE_ID primitive_id; ///< The primitive type
DCODE_PARAMS params; ///< A sequence of parameters used by
// the primitive
public:
AM_PRIMITIVE( AM_PRIMITIVE_ID aId = AMP_UNKNOWN )
{
primitive_id = aId;
}
~AM_PRIMITIVE() {}
/**
* Function GetExposure
* returns the first parameter in integer form. Some but not all primitives
* use the first parameter as an exposure control.
*/
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, int aAltColor, wxPoint aShapePos, bool aFilledShape );
private:
/** function ConvertShapeToPolygon
* convert a shape to an equivalent polygon.
* Arcs and circles are approximated by segments
* Useful when a shape is not a graphic primitive (shape with hole,
* rotated shape ... ) and cannot be easily drawn.
*/
void ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector<wxPoint>& aBuffer, bool aUnitsMetric);
};
typedef std::vector<AM_PRIMITIVE> AM_PRIMITIVES;
/**
* Struct APERTURE_MACRO
* helps support the "aperture macro" defined within standard RS274X.
*/
struct APERTURE_MACRO
{
wxString name; ///< The name of the aperture macro
AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs
/** 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, int aAltColor, wxPoint aShapePos, bool aFilledShape );
};
/**
* Struct APERTURE_MACRO_less_than
* is used by std:set<APERTURE_MACRO> instantiation which uses
* APERTURE_MACRO.name as its key.
*/
struct APERTURE_MACRO_less_than
{
// a "less than" test on two APERTURE_MACROs (.name wxStrings)
bool operator()( const APERTURE_MACRO& am1, const APERTURE_MACRO& am2 ) const
{
return am1.name.Cmp( am2.name ) < 0; // case specific wxString compare
}
};
/**
* Type APERTURE_MACRO_SET
* is a sorted collection of APERTURE_MACROS whose key is the name field in
* the APERTURE_MACRO.
*/
typedef std::set<APERTURE_MACRO, APERTURE_MACRO_less_than> APERTURE_MACRO_SET;
typedef std::pair<APERTURE_MACRO_SET::iterator, bool> APERTURE_MACRO_SET_PAIR;
#endif // ifndef _APERTURE_MACRO_H_
...@@ -49,6 +49,9 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( BOARD_ITEM* aParent ) : ...@@ -49,6 +49,9 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( BOARD_ITEM* aParent ) :
m_Shape = GBR_SEGMENT; m_Shape = GBR_SEGMENT;
m_Flashed = false; m_Flashed = false;
m_DCode = 0; m_DCode = 0;
m_UnitsMetric = false;
m_ImageNegative = false;
m_LayerNegative = false;
} }
...@@ -70,6 +73,10 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) : ...@@ -70,6 +73,10 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) :
m_Flashed = aSource.m_Flashed; m_Flashed = aSource.m_Flashed;
m_DCode = aSource.m_DCode; m_DCode = aSource.m_DCode;
m_PolyCorners = aSource.m_PolyCorners; m_PolyCorners = aSource.m_PolyCorners;
m_UnitsMetric = aSource.m_UnitsMetric;
m_ImageNegative = aSource.m_ImageNegative;
m_LayerNegative = aSource.m_LayerNegative;
} }
...@@ -176,12 +183,12 @@ bool GERBER_DRAW_ITEM::Save( FILE* aFile ) const ...@@ -176,12 +183,12 @@ bool GERBER_DRAW_ITEM::Save( FILE* aFile ) const
/*********************************************************************/ /*********************************************************************/
void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
const wxPoint& aOffset ) const wxPoint& aOffset )
/*********************************************************************/ /*********************************************************************/
{ {
static D_CODE dummyD_CODE( 0 ); // used when a D_CODE is not found. default D_CODE to draw a flashed item 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; bool isFilled;
int radius; int radius;
int halfPenWidth; int halfPenWidth;
...@@ -192,29 +199,29 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, ...@@ -192,29 +199,29 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode,
if( d_codeDescr == NULL ) if( d_codeDescr == NULL )
d_codeDescr = &dummyD_CODE; 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( color & HIGHT_LIGHT_FLAG )
{ color = ColorRefs[color & MASKCOLOR].m_LightColor;
if( brd->IsLayerVisible( GetLayer() ) == false )
return;
color = brd->GetLayerColor( GetLayer() ); alt_color = g_DrawBgColor ;
if( draw_mode & GR_SURBRILL ) if( m_Flags & DRAW_ERASED ) // draw in background color ("negative" color)
{ {
if( draw_mode & GR_AND ) EXCHG(color, alt_color);
color &= ~HIGHT_LIGHT_FLAG;
else
color |= HIGHT_LIGHT_FLAG;
}
if( color & HIGHT_LIGHT_FLAG )
color = ColorRefs[color & MASKCOLOR].m_LightColor;
} }
GRSetDrawMode( DC, draw_mode ); GRSetDrawMode( aDC, aDrawMode );
isFilled = DisplayOpt.DisplayPcbTrackFill ? true : false; isFilled = DisplayOpt.DisplayPcbTrackFill ? true : false;
...@@ -224,7 +231,7 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, ...@@ -224,7 +231,7 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode,
isFilled = (g_DisplayPolygonsModeSketch == false); isFilled = (g_DisplayPolygonsModeSketch == false);
if( m_Flags & DRAW_ERASED ) if( m_Flags & DRAW_ERASED )
isFilled = true; isFilled = true;
DrawGbrPoly( &panel->m_ClipBox, DC, color, aOffset, isFilled ); DrawGbrPoly( &aPanel->m_ClipBox, aDC, color, aOffset, isFilled );
break; break;
case GBR_CIRCLE: case GBR_CIRCLE:
...@@ -236,14 +243,14 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, ...@@ -236,14 +243,14 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode,
if( !isFilled ) if( !isFilled )
{ {
// draw the border of the pen's path using two circles, each as narrow as possible // draw the border of the pen's path using two circles, each as narrow as possible
GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, GRCircle( &aPanel->m_ClipBox, aDC, m_Start.x, m_Start.y,
radius - halfPenWidth, 0, color ); radius - halfPenWidth, 0, color );
GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, GRCircle( &aPanel->m_ClipBox, aDC, m_Start.x, m_Start.y,
radius + halfPenWidth, 0, color ); radius + halfPenWidth, 0, color );
} }
else // Filled mode else // Filled mode
{ {
GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, GRCircle( &aPanel->m_ClipBox, aDC, m_Start.x, m_Start.y,
radius, m_Size.x, color ); radius, m_Size.x, color );
} }
break; break;
...@@ -251,13 +258,13 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, ...@@ -251,13 +258,13 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode,
case GBR_ARC: case GBR_ARC:
if( !isFilled ) if( !isFilled )
{ {
GRArc1( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, GRArc1( &aPanel->m_ClipBox, aDC, m_Start.x, m_Start.y,
m_End.x, m_End.y, m_End.x, m_End.y,
m_ArcCentre.x, m_ArcCentre.y, 0, color ); m_ArcCentre.x, m_ArcCentre.y, 0, color );
} }
else else
{ {
GRArc1( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, GRArc1( &aPanel->m_ClipBox, aDC, m_Start.x, m_Start.y,
m_End.x, m_End.y, m_End.x, m_End.y,
m_ArcCentre.x, m_ArcCentre.y, m_ArcCentre.x, m_ArcCentre.y,
m_Size.x, color ); m_Size.x, color );
...@@ -268,17 +275,18 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode, ...@@ -268,17 +275,18 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode,
case GBR_SPOT_RECT: case GBR_SPOT_RECT:
case GBR_SPOT_OVAL: case GBR_SPOT_OVAL:
case GBR_SPOT_POLY: case GBR_SPOT_POLY:
case GBR_SPOT_MACRO:
isFilled = DisplayOpt.DisplayPadFill ? true : false; isFilled = DisplayOpt.DisplayPadFill ? true : false;
d_codeDescr->DrawFlashedShape( &panel->m_ClipBox, DC, color, d_codeDescr->DrawFlashedShape( this, &aPanel->m_ClipBox, aDC, color, alt_color,
m_Start, isFilled ); m_Start, isFilled );
break; break;
case GBR_SEGMENT: case GBR_SEGMENT:
if( !isFilled ) if( !isFilled )
GRCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y, GRCSegm( &aPanel->m_ClipBox, aDC, m_Start.x, m_Start.y,
m_End.x, m_End.y, m_Size.x, color ); m_End.x, m_End.y, m_Size.x, color );
else else
GRFillCSegm( &panel->m_ClipBox, DC, m_Start.x, GRFillCSegm( &aPanel->m_ClipBox, aDC, m_Start.x,
m_Start.y, m_End.x, m_End.y, m_Size.x, color ); m_Start.y, m_End.x, m_End.y, m_Size.x, color );
break; break;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
*/ */
#include "base_struct.h" #include "base_struct.h"
#include "class_board_item.h"
/* Shapes id for basic shapes ( .m_Shape member ) */ /* Shapes id for basic shapes ( .m_Shape member ) */
enum Gbr_Basic_Shapes { enum Gbr_Basic_Shapes {
...@@ -57,6 +58,8 @@ private: ...@@ -57,6 +58,8 @@ private:
public: public:
bool m_UnitsMetric; /* store here the gerber units (inch/mm).
* Used only to calculate aperture macros shapes sizes */
int m_Shape; // Shape and type of this gerber item int m_Shape; // Shape and type of this gerber item
wxPoint m_Start; // Line or arc start point or position of the shape wxPoint m_Start; // Line or arc start point or position of the shape
// for flashed items // for flashed items
...@@ -71,6 +74,8 @@ public: ...@@ -71,6 +74,8 @@ public:
// 0 for items that do not use DCodes (polygons) // 0 for items that do not use DCodes (polygons)
// or when unknown and normal values are 10 to 999 // or when unknown and normal values are 10 to 999
// values 0 to 9 can be used for special purposes // 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: public:
GERBER_DRAW_ITEM( BOARD_ITEM* aParent ); GERBER_DRAW_ITEM( BOARD_ITEM* aParent );
......
...@@ -96,10 +96,11 @@ const wxChar* D_CODE::ShowApertureType( APERTURE_T aType ) ...@@ -96,10 +96,11 @@ const wxChar* D_CODE::ShowApertureType( APERTURE_T aType )
return ret; return ret;
} }
/** Function Read_D_Code_File /** Function Read_D_Code_File
* Can be useful only with old RS274D Gerber file format. * Can be useful only with old RS274D Gerber file format.
* Is not needed with RS274X files format. * Is not needed with RS274X files format.
* These files need an auxiliary DCode file description. Ther is no defined file format for this. * These files need an auxiliary DCode file description. There is no defined file format for this.
* This function read a file format I needed a long time ago. * This function read a file format I needed a long time ago.
* reads in a dcode file assuming ALSPCB file format with ';' indicating comments. * reads in a dcode file assuming ALSPCB file format with ';' indicating comments.
* Format is like CSV but with optional ';' delineated comments: * Format is like CSV but with optional ';' delineated comments:
...@@ -165,7 +166,7 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName ) ...@@ -165,7 +166,7 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
if( ii >= 6 ) /* valeurs en mils */ if( ii >= 6 ) /* valeurs en mils */
{ {
sscanf( line, "%d,%d,%d,%d,%d,%d,%d", &ii, sscanf( line, "%d,%d,%d,%d,%d,%d,%d", &ii,
&dimH, &dimV, &drill, &dummy, &dummy, &type_outil ); &dimH, &dimV, &drill, &dummy, &dummy, &type_outil );
dimH = wxRound( dimH * dcode_scale ); dimH = wxRound( dimH * dcode_scale );
dimV = wxRound( dimV * dcode_scale ); dimV = wxRound( dimV * dcode_scale );
...@@ -279,7 +280,7 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems() ...@@ -279,7 +280,7 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
break; break;
default: default:
wxMessageBox( wxT("WinEDA_GerberFrame::CopyDCodesSizeToItems() error" ) ); wxMessageBox( wxT( "WinEDA_GerberFrame::CopyDCodesSizeToItems() error" ) );
break; break;
} }
} }
...@@ -291,15 +292,19 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems() ...@@ -291,15 +292,19 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
* Draw the dcode shape for flashed items. * Draw the dcode shape for flashed items.
* When an item is flashed, the DCode shape is the shape of the item * When an item is flashed, the DCode shape is the shape of the item
*/ */
void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor, void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent,
wxPoint aShapePos, bool aFilledShape ) EDA_Rect* aClipBox, wxDC* aDC, int aColor, int aAltColor,
wxPoint aShapePos, bool aFilledShape )
{ {
int radius; int radius;
switch( m_Shape ) switch( m_Shape )
{ {
case APT_MACRO:
GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor, aAltColor,
aShapePos, aFilledShape);
break;
case APT_MACRO: // TODO: current a round shape
case APT_CIRCLE: case APT_CIRCLE:
radius = m_Size.x >> 1; radius = m_Size.x >> 1;
if( !aFilledShape ) if( !aFilledShape )
...@@ -427,7 +432,7 @@ void D_CODE::DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, ...@@ -427,7 +432,7 @@ void D_CODE::DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC,
static void addHoleToPolygon( std::vector<wxPoint>& aBuffer, static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
APERTURE_DEF_HOLETYPE aHoleShape, APERTURE_DEF_HOLETYPE aHoleShape,
wxSize aSize, wxSize aSize,
wxPoint aAnchorPos ); wxPoint aAnchorPos );
/** function ConvertShapeToPolygon /** function ConvertShapeToPolygon
* convert a shape to an equivalent polygon. * convert a shape to an equivalent polygon.
...@@ -439,6 +444,7 @@ void D_CODE::ConvertShapeToPolygon() ...@@ -439,6 +444,7 @@ void D_CODE::ConvertShapeToPolygon()
{ {
wxPoint initialpos; wxPoint initialpos;
wxPoint currpos;; wxPoint currpos;;
m_PolyCorners.clear(); m_PolyCorners.clear();
switch( m_Shape ) switch( m_Shape )
...@@ -530,6 +536,7 @@ void D_CODE::ConvertShapeToPolygon() ...@@ -530,6 +536,7 @@ void D_CODE::ConvertShapeToPolygon()
case APT_POLYGON: case APT_POLYGON:
currpos.x = m_Size.x >> 1; // first point is on X axis currpos.x = m_Size.x >> 1; // first point is on X axis
initialpos = currpos; initialpos = currpos;
// rs274x said: m_EdgesCount = 3 ... 12 // rs274x said: m_EdgesCount = 3 ... 12
if( m_EdgesCount < 3 ) if( m_EdgesCount < 3 )
m_EdgesCount = 3; m_EdgesCount = 3;
...@@ -541,15 +548,16 @@ void D_CODE::ConvertShapeToPolygon() ...@@ -541,15 +548,16 @@ void D_CODE::ConvertShapeToPolygon()
RotatePoint( &currpos, ii * 3600 / m_EdgesCount ); RotatePoint( &currpos, ii * 3600 / m_EdgesCount );
m_PolyCorners.push_back( currpos ); m_PolyCorners.push_back( currpos );
} }
addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
if( m_Rotation ) // vertical oval, rotate polygon. if( m_Rotation ) // vertical oval, rotate polygon.
{ {
int angle = wxRound( m_Rotation*10 ); int angle = wxRound( m_Rotation * 10 );
for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ ) for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
{ {
// Remember the Y axis is from top to bottom when draw items. // Remember the Y axis is from top to bottom when draw items.
RotatePoint( &m_PolyCorners[jj], -angle ); RotatePoint( &m_PolyCorners[jj], -angle );
NEGATE(m_PolyCorners[jj].y); NEGATE( m_PolyCorners[jj].y );
} }
} }
break; break;
...@@ -561,6 +569,7 @@ void D_CODE::ConvertShapeToPolygon() ...@@ -561,6 +569,7 @@ void D_CODE::ConvertShapeToPolygon()
} }
} }
// The helper function for D_CODE::ConvertShapeToPolygon(). // The helper function for D_CODE::ConvertShapeToPolygon().
// Add a hole to a polygon // Add a hole to a polygon
static void addHoleToPolygon( std::vector<wxPoint>& aBuffer, static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
...@@ -569,6 +578,7 @@ static void addHoleToPolygon( std::vector<wxPoint>& aBuffer, ...@@ -569,6 +578,7 @@ static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
wxPoint aAnchorPos ) wxPoint aAnchorPos )
{ {
wxPoint currpos; wxPoint currpos;
if( aHoleShape == APT_DEF_ROUND_HOLE ) // build a round hole if( aHoleShape == APT_DEF_ROUND_HOLE ) // build a round hole
{ {
for( int ii = 0; ii <= SEGS_CNT; ii++ ) for( int ii = 0; ii <= SEGS_CNT; ii++ )
...@@ -579,9 +589,9 @@ static void addHoleToPolygon( std::vector<wxPoint>& aBuffer, ...@@ -579,9 +589,9 @@ static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
aBuffer.push_back( currpos ); aBuffer.push_back( currpos );
} }
aBuffer.push_back( aAnchorPos ); // link to outline aBuffer.push_back( aAnchorPos ); // link to outline
} }
if( aHoleShape == APT_DEF_RECT_HOLE ) // Create rectangular hole if( aHoleShape == APT_DEF_RECT_HOLE ) // Create rectangular hole
{ {
currpos.x = aSize.x / 2; currpos.x = aSize.x / 2;
currpos.y = aSize.y / 2; currpos.y = aSize.y / 2;
...@@ -593,7 +603,7 @@ static void addHoleToPolygon( std::vector<wxPoint>& aBuffer, ...@@ -593,7 +603,7 @@ static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
currpos.x += aSize.x; currpos.x += aSize.x;
aBuffer.push_back( currpos ); aBuffer.push_back( currpos );
currpos.y += aSize.y; currpos.y += aSize.y;
aBuffer.push_back( currpos ); // close hole aBuffer.push_back( currpos ); // close hole
aBuffer.push_back( aAnchorPos ); // link to outline aBuffer.push_back( aAnchorPos ); // link to outline
} }
} }
...@@ -2,6 +2,31 @@ ...@@ -2,6 +2,31 @@
/* dcode.h */ /* dcode.h */
/**************/ /**************/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _DCODE_H_ #ifndef _DCODE_H_
#define _DCODE_H_ #define _DCODE_H_
...@@ -9,7 +34,7 @@ ...@@ -9,7 +34,7 @@
#include <set> #include <set>
#include "base_struct.h" #include "base_struct.h"
class GERBER_DRAW_ITEM;
/** /**
* Enum APERTURE_T * Enum APERTURE_T
...@@ -42,6 +67,7 @@ enum APERTURE_DEF_HOLETYPE { ...@@ -42,6 +67,7 @@ enum APERTURE_DEF_HOLETYPE {
#define LAST_DCODE 999 #define LAST_DCODE 999
#define TOOLS_MAX_COUNT (LAST_DCODE + 1) #define TOOLS_MAX_COUNT (LAST_DCODE + 1)
class APERTURE_MACRO;
class D_CODE; class D_CODE;
...@@ -97,91 +123,8 @@ private: ...@@ -97,91 +123,8 @@ private:
// not used. // not used.
}; };
/**
* Enum AM_PRIMITIVE_ID
* is the set of all "aperture macro primitives" (primitive numbers). See
* Table 3 in http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
* aperture macro primitives are basic shapes which can be combined to create a complex shape
* This complex shape is flashed.
*/
enum AM_PRIMITIVE_ID {
AMP_CIRCLE = 1, // Circle. (diameter and position)
AMP_LINE2 = 2, // Line with rectangle ends. (Width, start and end pos + rotation)
AMP_LINE20 = 20, // Same as AMP_LINE2
AMP_LINE_CENTER = 21, // Rectangle. (height, width and center pos + rotation)
AMP_LINE_LOWER_LEFT = 22, // Rectangle. (height, width and lrft bottom corner pos + rotation)
AMP_EOF = 3, // End Of File marquer: not really a shape
AMP_OUTLINE = 4, // Free polyline (n corners + rotation)
AMP_POLYGON = 5, // Closed regular polygon(diameter, number of vertices (3 to 10), rotation)
AMP_MOIRE = 6, // A cross hair with n concentric circles + rotation
AMP_THERMAL = 7, // Thermal shape (pos, outer and inner dioameter, cross hair thickness + rotation)
};
typedef std::vector<DCODE_PARAM> DCODE_PARAMS; typedef std::vector<DCODE_PARAM> DCODE_PARAMS;
/**
* Struct AM_PRIMITIVE
* holds an aperture macro primitive as given in Table 3 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/
struct AM_PRIMITIVE
{
AM_PRIMITIVE_ID primitive_id; ///< The primitive type
DCODE_PARAMS params; ///< A sequence of parameters used by
// the primitive
/**
* Function GetExposure
* 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 );
}
};
typedef std::vector<AM_PRIMITIVE> AM_PRIMITIVES;
/**
* Struct APERTURE_MACRO
* helps support the "aperture macro" defined within standard RS274X.
*/
struct APERTURE_MACRO
{
wxString name; ///< The name of the aperture macro
AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs
};
/**
* Struct APERTURE_MACRO_less_than
* is used by std:set<APERTURE_MACRO> instantiation which uses
* APERTURE_MACRO.name as its key.
*/
struct APERTURE_MACRO_less_than
{
// a "less than" test on two APERTURE_MACROs (.name wxStrings)
bool operator()( const APERTURE_MACRO& am1, const APERTURE_MACRO& am2 ) const
{
return am1.name.Cmp( am2.name ) < 0; // case specific wxString compare
}
};
/**
* Type APERTURE_MACRO_SET
* is a sorted collection of APERTURE_MACROS whose key is the name field in
* the APERTURE_MACRO.
*/
typedef std::set<APERTURE_MACRO, APERTURE_MACRO_less_than> APERTURE_MACRO_SET;
typedef std::pair<APERTURE_MACRO_SET::iterator, bool> APERTURE_MACRO_SET_PAIR;
/** /**
* Class D_CODE * Class D_CODE
...@@ -206,15 +149,15 @@ class D_CODE ...@@ -206,15 +149,15 @@ class D_CODE
*/ */
public: public:
wxSize m_Size; /* Horizontal and vertical dimensions. */ wxSize m_Size; /* Horizontal and vertical dimensions. */
APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */ APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */
int m_Num_Dcode; /* D code ( >= 10 ) */ int m_Num_Dcode; /* D code ( >= 10 ) */
wxSize m_Drill; /* dimension of the hole (if any) */ wxSize m_Drill; /* dimension of the hole (if any) */
APERTURE_DEF_HOLETYPE m_DrillShape; /* shape of the hole (0 = no hole, round = 1, rect = 2) */ APERTURE_DEF_HOLETYPE m_DrillShape; /* shape of the hole (0 = no hole, round = 1, rect = 2) */
double m_Rotation; /* shape rotation in degrees */ double m_Rotation; /* shape rotation in degrees */
int m_EdgesCount; /* in apeture definition Polygon only: number of edges for the polygon */ int m_EdgesCount; /* in apeture definition Polygon only: number of edges for the polygon */
bool m_InUse; /* FALSE if not used */ bool m_InUse; /* FALSE if not used */
bool m_Defined; /* FALSE if not defined */ bool m_Defined; /* FALSE if not defined */
wxString m_SpecialDescr; wxString m_SpecialDescr;
public: public:
...@@ -250,16 +193,28 @@ public: ...@@ -250,16 +193,28 @@ public:
/** function DrawFlashedShape /** function DrawFlashedShape
* Draw the dcode shape for flashed items. * Draw the dcode shape for flashed items.
* When an item is flashed, the DCode shape is the shape of the item * 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( EDA_Rect* aClipBox, wxDC* aDC, int aColor, void DrawFlashedShape( GERBER_DRAW_ITEM* aParent,
wxPoint aShapePos, bool aFilledShape ); EDA_Rect* aClipBox, wxDC* aDC, int aColor, int aAltColor,
wxPoint aShapePos, bool aFilledShape );
/** function DrawFlashedPolygon /** function DrawFlashedPolygon
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners * a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
* Draw some Apertures shapes when they are defined as filled polygons. * 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 * APT_POLYGON is always a polygon, but some complex shapes are also converted to
* polygons (shapes with holes, some rotated shapes) * 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, void DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
bool aFilled, const wxPoint& aPosition ); 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*
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <set> #include <set>
#include "dcode.h" #include "dcode.h"
#include "class_gerber_draw_item.h"
#include "class_aperture_macro.h"
class WinEDA_GerberFrame; class WinEDA_GerberFrame;
class BOARD; class BOARD;
......
...@@ -76,123 +76,68 @@ static wxPoint LastPosition; ...@@ -76,123 +76,68 @@ static wxPoint LastPosition;
/** /**
* Function fillCircularGBRITEM * Function fillFlashedGBRITEM
* 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
* initializes a given GBRITEM so that it can draw a circle which is filled and * initializes a given GBRITEM so that it can draw a circle which is filled and
* has no pen border. * has no pen border.
* *
* @param aGbrItem The GBRITEM to fill in. * @param aGbrItem The GBRITEM to fill in.
* @param aAperture the associated type of aperture
* @param Dcode_index The DCODE value, like D14 * @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the GBRITEM * @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the flash * @param aPos The center point of the flash
* @param aDiameter The diameter of the round flash * @param aSize The diameter of the round flash
* @param isDark True if flash is positive and should use a drawing * @param aLayerNegative = true if the current layer is negative
* color other than the background color, else use the background color * @param aImageNegative = true if the current image is negative
* when drawing so that an erasure happens.
*/ */
static void fillRoundFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem, static void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index, APERTURE_T aAperture,
int aLayer, int Dcode_index,
const wxPoint& aPos, int aLayer,
int aDiameter, const wxPoint& aPos,
bool isDark ) wxSize aSize,
bool aLayerNegative,
bool aImageNegative )
{ {
aGbrItem->SetLayer( aLayer ); aGbrItem->SetLayer( aLayer );
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aDiameter; aGbrItem->m_Size = aSize;
aGbrItem->m_Start = aPos; aGbrItem->m_Start = aPos;
NEGATE( aGbrItem->m_Start.y ); NEGATE( aGbrItem->m_Start.y );
aGbrItem->m_End = aGbrItem->m_Start; aGbrItem->m_End = aGbrItem->m_Start;
aGbrItem->m_DCode = Dcode_index; aGbrItem->m_DCode = Dcode_index;
aGbrItem->m_Shape = GBR_SPOT_CIRCLE; aGbrItem->m_LayerNegative = aLayerNegative;
aGbrItem->m_ImageNegative = aImageNegative;
aGbrItem->m_Flashed = true; aGbrItem->m_Flashed = true;
switch( aAperture )
if( !isDark )
{ {
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;
/** case APT_OVAL:
* Function fillOvalOrRectFlashGBRITEM aGbrItem->m_Shape = GBR_SPOT_OVAL;
* initializes a given GBRITEM so that it can draw an oval or rectangular break;
* 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;
aGbrItem->m_Size = aSize; case APT_RECT:
aGbrItem->m_Shape = GBR_SPOT_RECT;
break;
aGbrItem->m_Start = aPos; case APT_MACRO:
NEGATE( aGbrItem->m_Start.y ); aGbrItem->m_Shape = GBR_SPOT_MACRO;
aGbrItem->m_End = aGbrItem->m_Start; break;
}
aGbrItem->m_DCode = Dcode_index; bool isDark = !(aGbrItem->m_LayerNegative ^ aGbrItem->m_ImageNegative);
aGbrItem->m_Shape = aShape;
/* 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 ) if( !isDark )
{ {
aGbrItem->m_Flags |= DRAW_ERASED; aGbrItem->m_Flags |= DRAW_ERASED;
...@@ -209,9 +154,8 @@ static void fillOvalOrRectFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem, ...@@ -209,9 +154,8 @@ static void fillOvalOrRectFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* @param aLayer The layer index to set into the GBRITEM * @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the flash * @param aPos The center point of the flash
* @param aDiameter The diameter of the round flash * @param aDiameter The diameter of the round flash
* @param isDark True if flash is positive and should use a drawing * @param aLayerNegative = true if the current layer is negative
* color other than the background color, else use the background color * @param aImageNegative = true if the current image is negative
* when drawing so that an erasure happens.
*/ */
static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index, int Dcode_index,
...@@ -219,7 +163,8 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, ...@@ -219,7 +163,8 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
const wxPoint& aStart, const wxPoint& aStart,
const wxPoint& aEnd, const wxPoint& aEnd,
int aWidth, int aWidth,
bool isDark ) bool aLayerNegative,
bool aImageNegative )
{ {
aGbrItem->SetLayer( aLayer ); aGbrItem->SetLayer( aLayer );
aGbrItem->m_Flashed = false; aGbrItem->m_Flashed = false;
...@@ -233,7 +178,15 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, ...@@ -233,7 +178,15 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
NEGATE( aGbrItem->m_End.y ); NEGATE( aGbrItem->m_End.y );
aGbrItem->m_DCode = Dcode_index; 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 ) if( !isDark )
{ {
aGbrItem->m_Flags |= DRAW_ERASED; aGbrItem->m_Flags |= DRAW_ERASED;
...@@ -267,20 +220,21 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, ...@@ -267,20 +220,21 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* same quadrant. * same quadrant.
* @param aDiameter The diameter of the round flash * @param aDiameter The diameter of the round flash
* @param aWidth is the pen width. * @param aWidth is the pen width.
* @param isDark True if flash is positive and should use a drawing * @param aLayerNegative = true if the current layer is negative
* color other than the background color, else use the background color * @param aImageNegative = true if the current image is negative
* when drawing so that an erasure happens.
*/ */
static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aLayer, static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aLayer,
const wxPoint& aStart, const wxPoint& aEnd, const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& rel_center, int aWidth, const wxPoint& rel_center, int aWidth,
bool clockwise, bool multiquadrant, bool isDark ) bool clockwise, bool multiquadrant,
bool aLayerNegative,
bool aImageNegative )
{ {
wxPoint center, delta; wxPoint center, delta;
aGbrItem->m_Shape = GBR_ARC; aGbrItem->m_Shape = GBR_ARC;
aGbrItem->SetLayer( aLayer ); 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; aGbrItem->m_Flashed = false;
if( multiquadrant ) if( multiquadrant )
...@@ -347,6 +301,15 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL ...@@ -347,6 +301,15 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL
NEGATE( aGbrItem->m_End.y ); NEGATE( aGbrItem->m_End.y );
NEGATE( aGbrItem->m_ArcCentre.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 ) if( !isDark )
{ {
aGbrItem->m_Flags |= DRAW_ERASED; aGbrItem->m_Flags |= DRAW_ERASED;
...@@ -379,23 +342,38 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL ...@@ -379,23 +342,38 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL
* same quadrant. * same quadrant.
* @param aDiameter The diameter of the round flash * @param aDiameter The diameter of the round flash
* @param aWidth is the pen width. * @param aWidth is the pen width.
* @param isDark True if flash is positive and should use a drawing * @param aLayerNegative = true if the current layer is negative
* color other than the background color, else use the background color * @param aImageNegative = true if the current image is negative
* when drawing so that an erasure happens.
*/ */
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& aStart, const wxPoint& aEnd,
const wxPoint& rel_center, 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 /* in order to calculate arc parameters, we use fillArcGBRITEM
* so we muse create a dummy track and use its geometric parameters * so we muse create a dummy track and use its geometric parameters
*/ */
static GERBER_DRAW_ITEM dummyGbrItem( NULL ); 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, fillArcGBRITEM( &dummyGbrItem, 0, 0,
aStart, aEnd, rel_center, 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). // 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 // Approximate arc by 36 segments per 360 degree
...@@ -457,14 +435,10 @@ static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGrbrItem, ...@@ -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", // 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 ); ) // ii, rot, start_arc.x, start_arc.y,end_arc.x, end_arc.y ); )
if( aGrbrItem->m_PolyCorners.size() == 0 ) if( aGbrItem->m_PolyCorners.size() == 0 )
aGrbrItem->m_PolyCorners.push_back( start_arc + center ); aGbrItem->m_PolyCorners.push_back( start_arc + center );
aGrbrItem->m_PolyCorners.push_back( end_arc + center ); aGbrItem->m_PolyCorners.push_back( end_arc + center );
if( !isDark )
{
aGrbrItem->m_Flags |= DRAW_ERASED;
}
start_arc = end_arc; start_arc = end_arc;
} }
} }
...@@ -537,10 +511,11 @@ wxPoint GERBER::ReadXYCoord( char*& Text ) ...@@ -537,10 +511,11 @@ wxPoint GERBER::ReadXYCoord( char*& Text )
if( fmt_scale < 0 || fmt_scale > 9 ) if( fmt_scale < 0 || fmt_scale > 9 )
fmt_scale = 4; fmt_scale = 4;
double scale_list[10] = double scale_list[10] =
{ 10000.0, 1000.0, 100.0, 10.0, {
1, 10000.0, 1000.0, 100.0, 10.0,
0.1, 0.01, 0.001, 0.0001, 0.00001 1,
}; 0.1, 0.01, 0.001, 0.0001,0.00001
};
real_scale = scale_list[fmt_scale]; real_scale = scale_list[fmt_scale];
if( m_GerbMetric ) if( m_GerbMetric )
...@@ -631,48 +606,16 @@ wxPoint GERBER::ReadIJCoord( char*& Text ) ...@@ -631,48 +606,16 @@ wxPoint GERBER::ReadIJCoord( char*& Text )
} }
current_coord = atoi( line ); current_coord = atoi( line );
double real_scale = 1.0; double real_scale = 1.0;
if( fmt_scale < 0 || fmt_scale > 9 )
fmt_scale = 4; // select scale 1.0
switch( fmt_scale ) double scale_list[10] =
{ {
case 0: 10000.0, 1000.0, 100.0, 10.0,
real_scale = 10000.0; 1,
break; 0.1, 0.01, 0.001, 0.0001,0.00001
};
case 1: real_scale = scale_list[fmt_scale];
real_scale = 1000.0;
break;
case 2:
real_scale = 100.0;
break;
case 3:
real_scale = 10.0;
break;
case 4:
break;
case 5:
real_scale = 0.1;
break;
case 6:
real_scale = 0.01;
break;
case 7:
real_scale = 0.001;
break;
case 8:
real_scale = 0.0001;
break;
case 9:
real_scale = 0.00001;
break;
}
if( m_GerbMetric ) if( m_GerbMetric )
real_scale = real_scale / 25.4; real_scale = real_scale / 25.4;
...@@ -740,7 +683,7 @@ int GERBER::ReturnDCodeNumber( char*& Text ) ...@@ -740,7 +683,7 @@ int GERBER::ReturnDCodeNumber( char*& Text )
bool GERBER::Execute_G_Command( char*& text, int G_commande ) 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 ) switch( G_commande )
{ {
...@@ -844,7 +787,7 @@ bool GERBER::Execute_G_Command( char*& text, int G_commande ) ...@@ -844,7 +787,7 @@ bool GERBER::Execute_G_Command( char*& text, int G_commande )
* Function scale * Function scale
* converts a distance given in floating point to our deci-mils * converts a distance given in floating point to our deci-mils
*/ */
static int scale( double aCoord, bool isMetric ) int scale( double aCoord, bool isMetric )
{ {
int ret; int ret;
...@@ -863,53 +806,15 @@ static int scale( double aCoord, bool isMetric ) ...@@ -863,53 +806,15 @@ static int scale( double aCoord, bool isMetric )
* deci-mils coordinate system. * deci-mils coordinate system.
* @return wxPoint - The gerbview coordinate system vector. * @return wxPoint - The gerbview coordinate system vector.
*/ */
static wxPoint mapPt( double x, double y, bool isMetric ) wxPoint mapPt( double x, double y, bool isMetric )
{ {
wxPoint ret( scale( x, isMetric ), wxPoint ret( scale( x, isMetric ), scale( y, isMetric ) );
scale( y, isMetric ) );
return ret; return ret;
} }
/** bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, char*& text, int D_commande )
* 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 ); wxSize size( 15, 15 );
...@@ -923,7 +828,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, ...@@ -923,7 +828,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
D_CODE* tool = NULL; D_CODE* tool = NULL;
wxString msg; 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 if( D_commande >= FIRST_DCODE ) // This is a "Set tool" command
{ {
...@@ -957,7 +862,8 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, ...@@ -957,7 +862,8 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
pcb->m_Drawings.Append( gbritem ); pcb->m_Drawings.Append( gbritem );
gbritem->m_Shape = GBR_POLYGON; gbritem->m_Shape = GBR_POLYGON;
gbritem->SetLayer( activeLayer ); gbritem->SetLayer( activeLayer );
gbritem->m_Flashed = false; gbritem->m_Flashed = false;
gbritem->m_UnitsMetric = m_GerbMetric;
} }
switch( m_Iterpolation ) switch( m_Iterpolation )
...@@ -965,21 +871,20 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, ...@@ -965,21 +871,20 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
case GERB_INTERPOL_ARC_NEG: case GERB_INTERPOL_ARC_NEG:
case GERB_INTERPOL_ARC_POS: case GERB_INTERPOL_ARC_POS:
gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() ); 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", // 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_PreviousPos.x, m_PreviousPos.y, m_CurrentPos.x,
m_CurrentPos.y, m_PolygonFillModeState, m_Iterpolation, m_360Arc_enbl ); ) // m_CurrentPos.y, m_PolygonFillModeState, m_Iterpolation, m_360Arc_enbl ); )
fillArcPOLY( pcb, gbritem, m_PreviousPos, fillArcPOLY( pcb, gbritem, m_PreviousPos,
m_CurrentPos, m_IJPos, m_CurrentPos, m_IJPos,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ? ( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl, false : true, m_360Arc_enbl, m_LayerNegative, m_ImageNegative );
!(m_LayerNegative ^ m_ImageNegative) );
break; break;
default: default:
gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() ); gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() );
D( printf( "Add poly edge %d,%d to %d,%d fill %d\n", // D( printf( "Add poly edge %d,%d to %d,%d fill %d\n",
m_PreviousPos.x, m_PreviousPos.y, // m_PreviousPos.x, m_PreviousPos.y,
m_CurrentPos.x, m_CurrentPos.y, m_Iterpolation ); ) // m_CurrentPos.x, m_CurrentPos.y, m_Iterpolation ); )
gbritem->m_Start = m_PreviousPos; // m_Start is used as temporary storage gbritem->m_Start = m_PreviousPos; // m_Start is used as temporary storage
NEGATE( gbritem->m_Start.y ); NEGATE( gbritem->m_Start.y );
...@@ -995,7 +900,6 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, ...@@ -995,7 +900,6 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
{ {
if( m_LayerNegative ^ m_ImageNegative ) if( m_LayerNegative ^ m_ImageNegative )
gbritem->m_Flags |= DRAW_ERASED; gbritem->m_Flags |= DRAW_ERASED;
D( printf( "\nm_Flags=0x%08X\n", gbritem->m_Flags ); )
} }
break; break;
} }
...@@ -1033,11 +937,11 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, ...@@ -1033,11 +937,11 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
{ {
case GERB_INTERPOL_LINEAR_1X: case GERB_INTERPOL_LINEAR_1X:
gbritem = new GERBER_DRAW_ITEM( pcb ); gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem ); pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); ) // D( printf( "R:%p\n", gbritem ); )
fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos, fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, size.x, m_CurrentPos, size.x, m_LayerNegative, m_ImageNegative );
!(m_LayerNegative ^ m_ImageNegative) );
break; break;
case GERB_INTERPOL_LINEAR_01X: case GERB_INTERPOL_LINEAR_01X:
...@@ -1049,13 +953,14 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, ...@@ -1049,13 +953,14 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
case GERB_INTERPOL_ARC_NEG: case GERB_INTERPOL_ARC_NEG:
case GERB_INTERPOL_ARC_POS: case GERB_INTERPOL_ARC_POS:
gbritem = new GERBER_DRAW_ITEM( pcb ); gbritem = new GERBER_DRAW_ITEM( pcb );
gbritem->m_UnitsMetric = m_GerbMetric;
pcb->m_Drawings.Append( gbritem ); pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); ) // D( printf( "R:%p\n", gbritem ); )
fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos, fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, m_IJPos, size.x, m_CurrentPos, m_IJPos, size.x,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ? ( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl, false : true, m_360Arc_enbl,
!(m_LayerNegative ^ m_ImageNegative) ); m_LayerNegative, m_ImageNegative );
break; break;
default: default:
...@@ -1082,277 +987,13 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame, ...@@ -1082,277 +987,13 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
aperture = tool->m_Shape; aperture = tool->m_Shape;
} }
switch( aperture ) gbritem = new GERBER_DRAW_ITEM( pcb );
{ gbritem->m_UnitsMetric = m_GerbMetric;
case APT_POLYGON: // flashed regular polygon pcb->m_Drawings.Append( gbritem );
case APT_CIRCLE: // D( printf( "R:%p dcode %d layer %d\n", gbritem, dcode, activeLayer ); )
gbritem = new GERBER_DRAW_ITEM( pcb ); fillFlashedGBRITEM( gbritem, aperture,
pcb->m_Drawings.Append( gbritem ); dcode, activeLayer, m_CurrentPos,
D( printf( "R:%p\n", gbritem ); ) size, m_LayerNegative, m_ImageNegative );
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 );
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 );
// 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;
}
}
}
break;
default:
break;
}
m_PreviousPos = m_CurrentPos; m_PreviousPos = m_CurrentPos;
break; break;
......
...@@ -173,8 +173,7 @@ bool GERBER::ExecuteRS274XCommand( int command, ...@@ -173,8 +173,7 @@ bool GERBER::ExecuteRS274XCommand( int command,
double conv_scale = m_GerbMetric ? PCB_INTERNAL_UNIT / double conv_scale = m_GerbMetric ? PCB_INTERNAL_UNIT /
25.4 : PCB_INTERNAL_UNIT; 25.4 : PCB_INTERNAL_UNIT;
D( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF, // D( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF, command & 0xFF ); )
command & 0xFF ); )
switch( command ) switch( command )
{ {
...@@ -663,7 +662,7 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ], ...@@ -663,7 +662,7 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ],
break; break;
case AMP_POLYGON: case AMP_POLYGON:
paramCount = 4; paramCount = 6;
break; break;
case AMP_MOIRE: case AMP_MOIRE:
...@@ -703,7 +702,8 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ], ...@@ -703,7 +702,8 @@ bool GERBER::ReadApertureMacro( char buff[GERBER_BUFZ],
if( i < paramCount ) // maybe some day we can throw an exception and if( i < paramCount ) // maybe some day we can throw an exception and
// track a line number // 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 // there are more parameters to read if this is an AMP_OUTLINE
if( prim.primitive_id == AMP_OUTLINE ) if( prim.primitive_id == AMP_OUTLINE )
......
/* Bits characterizing cell */ /* Bits characterizing cell */
#define HOLE (char)0x01 /* a conducting hole or obstacle */ #define HOLE 0x01 /* a conducting hole or obstacle */
#define CELL_is_MODULE (char)0x02 /* auto placement occupied by a module */ #define CELL_is_MODULE 0x02 /* auto placement occupied by a module */
#define CELL_is_EDGE (char)0x20 /* Area and auto-placement: limiting cell #define CELL_is_EDGE 0x20 /* Area and auto-placement: limiting cell
* contour (Board, Zone) */ * 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 */ * 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 */ /* Bit masks for presence of obstacles to autorouting */
#define OCCUPE 1 /* Autorouting: obstacle tracks and vias. */ #define OCCUPE 1 /* Autorouting: obstacle tracks and vias. */
......
...@@ -65,7 +65,7 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( PLOTTER* plotter, ...@@ -65,7 +65,7 @@ void WinEDA_BasePcbFrame::Plot_Serigraphie( PLOTTER* plotter,
Plot_Edges_Modules( plotter, m_Pcb, masque_layer, trace_mode ); Plot_Edges_Modules( plotter, m_Pcb, masque_layer, trace_mode );
/* Plot pads (creates pads outlines, for pads on silkscreen layers) */ /* 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 // Calculate the mask layers of allowed layers for pads
if( !g_pcb_plot_options.PlotPadsOnSilkLayer ) if( !g_pcb_plot_options.PlotPadsOnSilkLayer )
layersmask_plotpads &= ~(SILKSCREEN_LAYER_BACK || SILKSCREEN_LAYER_FRONT); 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