diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 29d9d4dd2f..bc7bdc0d10 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -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 +================================================================================ +++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 ================================================================================ ++gerbview: diff --git a/gerbview/class_aperture_macro.cpp b/gerbview/class_aperture_macro.cpp index 83a1498cde..c47a3b417a 100644 --- a/gerbview/class_aperture_macro.cpp +++ b/gerbview/class_aperture_macro.cpp @@ -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 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 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,61 +298,102 @@ 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; iparams[1].GetValue( tool ); - int rotation = wxRound(params[numPoints * 2 + 4].GetValue( tool ) * 10.0); - - printf( "AMP_OUTLINE:\n" ); - printf( " exposure: %g\n", exposure ); - printf( " # points: %d\n", numPoints ); - - // numPoints does not include the starting point, so add 1. - for( int i = 0; iparams[i * 2 + 2 + 0].GetValue( tool ), - this->params[i * 2 + 2 + 1].GetValue( tool ) - ); - } - - printf( " rotation: %g\n", (float)rotation/10 ); + 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); } -#endif + // 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: - case AMP_POLYGON: - case AMP_EOF: default: - - // not yet supported, waiting for you. + 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& aBuffer, bool aUnitsMetric) +void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, + std::vector& 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 ); } } diff --git a/gerbview/class_aperture_macro.h b/gerbview/class_aperture_macro.h index 8df8b8e6cf..07221c5291 100644 --- a/gerbview/class_aperture_macro.h +++ b/gerbview/class_aperture_macro.h @@ -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 ); }; diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index 6044787001..1cb9208cf3 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -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( brd->IsLayerVisible( GetLayer() ) == false ) + return; + + color = brd->GetLayerColor( GetLayer() ); + + 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; + + alt_color = g_DrawBgColor ; + if( m_Flags & DRAW_ERASED ) // draw in background color ("negative" color) { - color = g_DrawBgColor; - } - else - { - if( brd->IsLayerVisible( GetLayer() ) == false ) - return; - - color = brd->GetLayerColor( GetLayer() ); - - 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; + 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; diff --git a/gerbview/class_gerber_draw_item.h b/gerbview/class_gerber_draw_item.h index c5c36c8db9..0dd37e1e01 100644 --- a/gerbview/class_gerber_draw_item.h +++ b/gerbview/class_gerber_draw_item.h @@ -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 ); diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp index 55bae2ee1a..5d353ad55d 100644 --- a/gerbview/dcode.cpp +++ b/gerbview/dcode.cpp @@ -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: diff --git a/gerbview/dcode.h b/gerbview/dcode.h index a98665d13f..434c881861 100644 --- a/gerbview/dcode.h +++ b/gerbview/dcode.h @@ -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 ); diff --git a/gerbview/gerber_test_files/aperture_macro-no_param-test.gbx b/gerbview/gerber_test_files/aperture_macro-no_param-test.gbx new file mode 100644 index 0000000000..f586dbe260 --- /dev/null +++ b/gerbview/gerber_test_files/aperture_macro-no_param-test.gbx @@ -0,0 +1,82 @@ +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* diff --git a/gerbview/rs274d.cpp b/gerbview/rs274d.cpp index d614ef5e74..154a376e6a 100644 --- a/gerbview/rs274d.cpp +++ b/gerbview/rs274d.cpp @@ -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; + + case APT_OVAL: + aGbrItem->m_Shape = GBR_SPOT_OVAL; + break; + + case APT_RECT: + aGbrItem->m_Shape = GBR_SPOT_RECT; + break; + + case APT_MACRO: + aGbrItem->m_Shape = GBR_SPOT_MACRO; + break; } -} + bool isDark = !(aGbrItem->m_LayerNegative ^ aGbrItem->m_ImageNegative); -/** - * 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; - - aGbrItem->m_Size = aSize; - - aGbrItem->m_Start = aPos; - NEGATE( aGbrItem->m_Start.y ); - aGbrItem->m_End = aGbrItem->m_Start; - - aGbrItem->m_DCode = Dcode_index; - 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 ) { 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; iparams[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; diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp index 06e80acfec..d74eae706a 100644 --- a/gerbview/rs274x.cpp +++ b/gerbview/rs274x.cpp @@ -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 ) diff --git a/pcbnew/cell.h b/pcbnew/cell.h index 79669aba02..ab255402e8 100644 --- a/pcbnew/cell.h +++ b/pcbnew/cell.h @@ -1,11 +1,11 @@ /* 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. */ diff --git a/pcbnew/plot_rtn.cpp b/pcbnew/plot_rtn.cpp index e9801cd3c8..af78d1c326 100644 --- a/pcbnew/plot_rtn.cpp +++ b/pcbnew/plot_rtn.cpp @@ -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);