From bc0d79d587fad91ec2febbeca110de32e54d291f Mon Sep 17 00:00:00 2001
From: jean-pierre charras <jp.charras@wanadoo.fr>
Date: Sun, 3 Oct 2010 17:39:06 +0200
Subject: [PATCH] finished Draw functions for aperture macros.  Now aperture
 macros are drawn correctly.  Known bug: aperture macros having parameters are
 incorrect: parameters are not transmited correctly. Work still in progress.

---
 CHANGELOG.txt                                 |   8 +
 gerbview/class_aperture_macro.cpp             | 493 +++++++++++----
 gerbview/class_aperture_macro.h               |  39 +-
 gerbview/class_gerber_draw_item.cpp           |  45 +-
 gerbview/class_gerber_draw_item.h             |   2 +
 gerbview/dcode.cpp                            |   5 +-
 gerbview/dcode.h                              |  15 +-
 .../aperture_macro-no_param-test.gbx          |  82 +++
 gerbview/rs274d.cpp                           | 589 ++++--------------
 gerbview/rs274x.cpp                           |   8 +-
 pcbnew/cell.h                                 |  10 +-
 pcbnew/plot_rtn.cpp                           |   2 +-
 12 files changed, 654 insertions(+), 644 deletions(-)
 create mode 100644 gerbview/gerber_test_files/aperture_macro-no_param-test.gbx

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 <jean-pierre.charras@gipsa-lab.inpg.fr>
+================================================================================
+++gerbview:
+    finished Draw functions for aperture macros.
+    Now aperture macros are draww correctly.
+    Known bug: aperture macros having parameters are incorrect: parameters are not transmited correctly.
+    Work still in progress.
+
 2010-sept-28, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
 ================================================================================
 ++gerbview:
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<wxPoint> polybuffer;     // create a static buffer to avoid a lot of memory reallocation
     polybuffer.clear();
 
     wxPoint curPos = aShapePos;
-    D_CODE*  tool  = aParent->GetDcodeDescr();
-    bool gerberMetric = aParent->m_UnitsMetric;
+    D_CODE* tool   = aParent->GetDcodeDescr();
+    bool    gerberMetric = aParent->m_UnitsMetric;
+    int rotation;
+    if( mapExposure( aParent ) == false )
+    {
+        EXCHG(aColor, aAltColor);
+    }
+
     switch( primitive_id )
     {
     case AMP_CIRCLE:        // Circle, given diameter and position
@@ -70,9 +144,8 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
         /* Generated by an aperture macro declaration like:
          * "1,1,0.3,0.5, 1.0*"
          * type (1), exposure, diameter, pos.x, pos.y
-         * type is not stored in parameters list, so the first parameter is pos.x
+         * type is not stored in parameters list, so the first parameter is exposure
          */
-        int exposure = params[0].GetValue( tool );
         curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), gerberMetric );
         int radius = scale( params[1].GetValue( tool ), gerberMetric ) / 2;
         if( !aFilledShape )
@@ -88,22 +161,24 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
         /* Generated by an aperture macro declaration like:
          * "2,1,0.3,0,0, 0.5, 1.0,-135*"
          * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
-         * type is not stored in parameters list, so the first parameter is pos.x
+         * type is not stored in parameters list, so the first parameter is exposure
          */
-        int exposure = params[0].GetValue( tool );
-        ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
+        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
+
         // shape rotation:
-        int rotation = wxRound(params[6].GetValue( tool ) * 10.0);
-        if (rotation)
+        rotation = wxRound( params[6].GetValue( tool ) * 10.0 );
+        if( rotation )
         {
             for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
-                RotatePoint(&polybuffer[ii], rotation);
+                RotatePoint( &polybuffer[ii], rotation );
         }
+
         // Move to current position:
         for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
             polybuffer[ii] += curPos;
 
-        GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
+        GRClosedPoly( aClipBox, aDC,
+                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
     }
     break;
 
@@ -112,21 +187,24 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
         /* Generated by an aperture macro declaration like:
          * "21,1,0.3,0.03,0,0,-135*"
          * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
-         * type is not stored in parameters list, so the first parameter is pos.x
+         * type is not stored in parameters list, so the first parameter is exposure
          */
-        int exposure = params[0].GetValue( tool );
-        ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
+        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
+
         // shape rotation:
-        int rotation = wxRound(params[5].GetValue( tool ) * 10.0);
-        if (rotation)
+        rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
+        if( rotation )
         {
             for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
-                RotatePoint(&polybuffer[ii], rotation);
+                RotatePoint( &polybuffer[ii], rotation );
         }
+
         // Move to current position:
         for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
             polybuffer[ii] += curPos;
-        GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
+
+        GRClosedPoly( aClipBox, aDC,
+                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
     }
     break;
 
@@ -135,44 +213,64 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
         /* Generated by an aperture macro declaration like:
          * "22,1,0.3,0.03,0,0,-135*"
          * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
-         * type is not stored in parameters list, so the first parameter is pos.x
+         * type is not stored in parameters list, so the first parameter is exposure
          */
-        int exposure = params[0].GetValue( tool );
-        ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
+        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
+
         // shape rotation:
-        int rotation = wxRound(params[5].GetValue( tool ) * 10.0);
-        if (rotation)
+        rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
+        if( rotation )
         {
             for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
-                RotatePoint(&polybuffer[ii], rotation);
+                RotatePoint( &polybuffer[ii], rotation );
         }
+
         // Move to current position:
         for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
             polybuffer[ii] += curPos;
-        GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
+
+        GRClosedPoly( aClipBox, aDC,
+                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
     }
     break;
 
     case AMP_THERMAL:
     {
         /* Generated by an aperture macro declaration like:
-         * "7,0,0,1.0,0.3,0.01,-13*"
+         * "7, 0,0,1.0,0.3,0.01,-13*"
          * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
-         * type is not stored in parameters list, so the first parameter is pos.x
+         * type is not stored in parameters list, so the first parameter is center.x
          */
-        ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
+        curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), gerberMetric );
+/*        int outerRadius   = scale( params[2].GetValue( tool ), gerberMetric ) / 2;
+        if( !aFilledShape )
+            GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerRadius, aColor );
+        else
+            GRFilledCircle( aClipBox, aDC, curPos, outerRadius, aColor );
+*/
+        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
+
         // shape rotation:
-        int rotation = wxRound(params[6].GetValue( tool ) * 10.0);
-        if (rotation)
+        rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
+
+        // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer.
+        // We must draw 4 sub-shapes rotated by 90 deg
+        std::vector<wxPoint> subshape_poly;
+        for( int ii = 0; ii < 4; ii++ )
         {
-            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
-                RotatePoint(&polybuffer[ii], rotation);
+            subshape_poly = polybuffer;
+            int sub_rotation = rotation + 900 * ii;
+            for( unsigned jj = 0; jj < subshape_poly.size(); jj++ )
+                RotatePoint( &subshape_poly[jj], sub_rotation );
+
+            // Move to current position:
+            for( unsigned jj = 0; jj < subshape_poly.size(); jj++ )
+                subshape_poly[jj] += curPos;
+
+            GRClosedPoly( aClipBox, aDC,
+                          subshape_poly.size(), &subshape_poly[0], true, aAltColor,
+                          aAltColor );
         }
-        // Move to current position:
-        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
-            polybuffer[ii] += curPos;
-        GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
-printf("    AMP_THERMAL %d\n",polybuffer.size());
     }
     break;
 
@@ -186,13 +284,13 @@ printf("    AMP_THERMAL %d\n",polybuffer.size());
          * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
          * type is not stored in parameters list, so the first parameter is pos.x
          */
-        int outerDiam = scale( params[2].GetValue( tool ), gerberMetric );
+        int outerDiam    = scale( params[2].GetValue( tool ), gerberMetric );
         int penThickness = scale( params[3].GetValue( tool ), gerberMetric );
         int gap = scale( params[4].GetValue( tool ), gerberMetric );
-        int numCircles = wxRound(params[5].GetValue( tool ));
+        int numCircles = wxRound( params[5].GetValue( tool ) );
 
         // adjust outerDiam by this on each nested circle
-        int diamAdjust = (gap + penThickness);//*2;     //Should we use * 2 ?
+        int diamAdjust = (gap + penThickness); //*2;     //Should we use * 2 ?
         for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
         {
             if( outerDiam <= 0 )
@@ -200,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; i<numPoints + 1; ++i )
         {
-            int exposure = params[0].GetValue( tool );
-            int numPoints = (int) this->params[1].GetValue( tool );
-            int rotation = wxRound(params[numPoints * 2 + 4].GetValue( tool ) * 10.0);
-
-            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;  i<numPoints + 1;  ++i )
-            {
-                printf( " [%d]: X=%g  Y=%g\n", i,
-                        this->params[i * 2 + 2 + 0].GetValue( tool ),
-                        this->params[i * 2 + 2 + 1].GetValue( tool )
-                        );
-            }
-
-            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<wxPoint>& aBuffer, bool aUnitsMetric)
+void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM*     aParent,
+                                          std::vector<wxPoint>& aBuffer,
+                                          bool                  aUnitsMetric )
 {
-    D_CODE*  tool  = aParent->GetDcodeDescr();
+    D_CODE* tool = aParent->GetDcodeDescr();
+
     switch( primitive_id )
     {
     case AMP_CIRCLE:        // Circle, currently convertion not needed
@@ -280,31 +422,33 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector
     case AMP_LINE2:
     case AMP_LINE20:        // Line with rectangle ends. (Width, start and end pos + rotation)
     {
-        int     width = scale( this->params[1].GetValue( tool ), aUnitsMetric );
-        wxPoint start = mapPt( this->params[2].GetValue( tool ),
-                               this->params[3].GetValue( tool ), aUnitsMetric );
-        wxPoint end = mapPt( this->params[4].GetValue( tool ),
-                             this->params[5].GetValue( tool ), aUnitsMetric );
+        int     width = scale( params[1].GetValue( tool ), aUnitsMetric );
+        wxPoint start = mapPt( params[2].GetValue( tool ),
+                               params[3].GetValue( tool ), aUnitsMetric );
+        wxPoint end = mapPt( params[4].GetValue( tool ),
+                             params[5].GetValue( tool ), aUnitsMetric );
         wxPoint delta = end - start;
-        int len = wxRound(hypot(delta.x, delta.y));
+        int     len   = wxRound( hypot( delta.x, delta.y ) );
+
         // To build the polygon, we must create a horizonta polygon starting to "start"
         // and rotate it to have it end point to "end"
         wxPoint currpt;
-        currpt.y += width/2;        // Upper left
-        aBuffer.push_back(currpt);
-        currpt.x = len;            // Upper right
-        aBuffer.push_back(currpt);
-        currpt.y -= width;          // lower right
-        aBuffer.push_back(currpt);
-        currpt.x = 0;              // Upper left
-        aBuffer.push_back(currpt);
+        currpt.y += width / 2;          // Upper left
+        aBuffer.push_back( currpt );
+        currpt.x = len;                 // Upper right
+        aBuffer.push_back( currpt );
+        currpt.y -= width;              // lower right
+        aBuffer.push_back( currpt );
+        currpt.x = 0;                   // Upper left
+        aBuffer.push_back( currpt );
+
         // Rotate rectangle and move it to the actual start point
-        int angle = wxRound( atan2(delta.y, delta.x) * 1800.0 / M_PI );
+        int angle = wxRound( atan2( delta.y, delta.x ) * 1800.0 / M_PI );
         for( unsigned ii = 0; ii < 4; ii++ )
         {
-            RotatePoint(&aBuffer[ii], -angle);
+            RotatePoint( &aBuffer[ii], -angle );
             aBuffer[ii] += start;
-            NEGATE(aBuffer[ii].y);
+            NEGATE( aBuffer[ii].y );
         }
     }
     break;
@@ -312,77 +456,149 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector
     case AMP_LINE_CENTER:
     {
         wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
-        wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
+        wxPoint pos  = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
+
         // Build poly:
-        pos.x -= size.x/2;
-        pos.y -= size.y/2;        // Lower left
-        aBuffer.push_back(pos);
-        pos.y += size.y;          // Upper left
-        aBuffer.push_back(pos);
-        pos.x += size.x;          // Upper right
-        aBuffer.push_back(pos);
-        pos.y -= size.y;          // lower right
-        aBuffer.push_back(pos);
+        pos.x -= size.x / 2;
+        pos.y -= size.y / 2;        // Lower left
+        aBuffer.push_back( pos );
+        pos.y += size.y;            // Upper left
+        aBuffer.push_back( pos );
+        pos.x += size.x;            // Upper right
+        aBuffer.push_back( pos );
+        pos.y -= size.y;            // lower right
+        aBuffer.push_back( pos );
     }
     break;
 
     case AMP_LINE_LOWER_LEFT:
     {
         wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
-        wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
+        wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue(
+                                       tool ), aUnitsMetric );
+
         // Build poly:
-        NEGATE(lowerLeft.y);
-        aBuffer.push_back(lowerLeft);
+        NEGATE( lowerLeft.y );
+        aBuffer.push_back( lowerLeft );
         lowerLeft.y += size.y;          // Upper left
-        aBuffer.push_back(lowerLeft);
+        aBuffer.push_back( lowerLeft );
         lowerLeft.x += size.x;          // Upper right
-        aBuffer.push_back(lowerLeft);
+        aBuffer.push_back( lowerLeft );
         lowerLeft.y -= size.y;          // lower right
-        aBuffer.push_back(lowerLeft);
+        aBuffer.push_back( lowerLeft );
+
         // Negate y coordinates:
         for( unsigned ii = 0; ii < aBuffer.size(); ii++ )
-            NEGATE(aBuffer[ii].y);
+            NEGATE( aBuffer[ii].y );
     }
     break;
 
     case AMP_THERMAL:
     {
-        int outerDiam = scale( this->params[2].GetValue( tool ), aUnitsMetric );
-        int innerDiam = scale( this->params[3].GetValue( tool ), aUnitsMetric );
+        // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
+        // rotated by 90, 180 and 270 deg.
+        // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
+        int outerRadius   = scale( params[2].GetValue( tool ), aUnitsMetric ) / 2;
+        int innerRadius   = scale( params[3].GetValue( tool ), aUnitsMetric ) / 2;
+        int halfthickness = scale( params[4].GetValue( tool ), aUnitsMetric ) / 2;
+        int angle_start   = wxRound( asin(
+                                         (double) halfthickness / innerRadius ) * 1800 / M_PI );
+
+        // Draw shape in the first cadrant (X and Y > 0)
+        wxPoint pos, startpos;
+
+        // Inner arc
+        startpos.x = innerRadius;
+        int angle_end = 900 - angle_start;
+        int angle;
+        for( angle = angle_start; angle < angle_end; angle += 100 )
+        {
+            pos = startpos;
+            RotatePoint( &pos, angle );
+            aBuffer.push_back( pos );
+        }
+
+        // Last point
+        pos = startpos;
+        RotatePoint( &pos, angle_end );
+        aBuffer.push_back( pos );
+
+        // outer arc
+        startpos.x  = outerRadius;
+        startpos.y  = 0;
+        angle_start = wxRound( asin( (double) halfthickness / outerRadius ) * 1800 / M_PI );
+        angle_end   = 900 - angle_start;
+
+        // First point, near Y axis, outer arc
+        for( angle = angle_end; angle > angle_start; angle -= 100 )
+        {
+            pos = startpos;
+            RotatePoint( &pos, angle );
+            aBuffer.push_back( pos );
+        }
+
+        // last point
+        pos = startpos;
+        RotatePoint( &pos, angle_start );
+        aBuffer.push_back( pos );
+
+        aBuffer.push_back( aBuffer[0] );  // Close poly
     }
     break;
 
     case AMP_MOIRE:     // A cross hair with n concentric circles. Only the cros is build as polygon
                         // because circles can be drawn easily
     {
-        int crossHairThickness = scale( this->params[6].GetValue( tool ), aUnitsMetric );
-        int crossHairLength = scale( this->params[7].GetValue( tool ), aUnitsMetric );
+        int crossHairThickness = scale( params[6].GetValue( tool ), aUnitsMetric );
+        int crossHairLength    = scale( params[7].GetValue( tool ), aUnitsMetric );
+
         // Create cross. First create 1/4 of the shape.
         // Others point are the same, totated by 90, 180 and 270 deg
-        wxPoint pos(crossHairThickness/2, crossHairLength/2);
-        aBuffer.push_back(pos);
-        pos.y = crossHairThickness/2;
-        aBuffer.push_back(pos);
-        pos.x = -crossHairLength/2;
-        aBuffer.push_back(pos);
-        pos.y = -crossHairThickness/2;
-        aBuffer.push_back(pos);
-        // Copy these 4 points, rotated by 90, 180 and 270 deg
+        wxPoint pos( crossHairThickness / 2, crossHairLength / 2 );
+        aBuffer.push_back( pos );
+        pos.y = crossHairThickness / 2;
+        aBuffer.push_back( pos );
+        pos.x = -crossHairLength / 2;
+        aBuffer.push_back( pos );
+        pos.y = -crossHairThickness / 2;
+        aBuffer.push_back( pos );
+
+        // Copy the 4 shape, rotated by 90, 180 and 270 deg
         for( int jj = 900; jj <= 2700; jj += 900 )
         {
             for( int ii = 0; ii < 4; ii++ )
             {
                 pos = aBuffer[ii];
-                RotatePoint(&pos,jj);
-                aBuffer.push_back(pos);
+                RotatePoint( &pos, jj );
+                aBuffer.push_back( pos );
             }
         }
     }
     break;
 
-    case AMP_UNKNOWN:
     case AMP_OUTLINE:
-    case AMP_POLYGON:
+        // already is a polygon. Do nothing
+        break;
+
+    case AMP_POLYGON:   // Creates a regular polygon
+    {
+        int vertexcount = wxRound( params[1].GetValue( tool ) );
+        int radius    = scale( params[4].GetValue( tool ), aUnitsMetric ) / 2;
+        // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
+        if( vertexcount < 3 )
+            vertexcount = 3;
+        if( vertexcount > 10 )
+            vertexcount = 10;
+        for( int ii = 0; ii <= vertexcount; ii++ )
+        {
+            wxPoint pos( radius, 0);
+            RotatePoint( &pos, ii * 3600 / vertexcount );
+            aBuffer.push_back( pos );
+        }
+    }
+        break;
+
+    case AMP_UNKNOWN:
     case AMP_EOF:
         break;
     }
@@ -394,15 +610,16 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector
  * When an item is flashed, this is the shape of the item
  */
 void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent,
-                                             EDA_Rect*         aClipBox,
-                                             wxDC*             aDC,
-                                             int               aColor,
-                                             wxPoint           aShapePos,
-                                             bool              aFilledShape )
+                                             EDA_Rect* aClipBox, wxDC* aDC,
+                                             int aColor, int aAltColor,
+                                             wxPoint aShapePos, bool aFilledShape )
 {
     for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
          prim_macro != primitives.end(); ++prim_macro )
     {
-        prim_macro->DrawBasicShape( aParent, aClipBox, aDC, aColor, aShapePos, aFilledShape );
+        prim_macro->DrawBasicShape( aParent, aClipBox, aDC,
+                                    aColor, aAltColor,
+                                    aShapePos,
+                                    aFilledShape );
     }
 }
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;  i<numPoints + 1;  ++i )
-                            {
-                                printf( " [%d]: X=%g  Y=%g\n", i,
-                                        p->params[i * 2 + 2 + 0].GetValue( tool ),
-                                        p->params[i * 2 + 2 + 1].GetValue( tool )
-                                        );
-                            }
-
-                            printf( " rotation: %g\n", p->params[numPoints * 2 + 4].GetValue( tool ) );
-                        }
-#endif
-                        break;
-
-                    case AMP_POLYGON:
-                    case AMP_EOF:
-                    default:
-
-                        // not yet supported, waiting for you.
-                        break;
-                    }
-                }
-#endif
-            }
-            break;
-
-            default:
-                break;
-            }
-
+            gbritem = new GERBER_DRAW_ITEM( pcb );
+            gbritem->m_UnitsMetric = m_GerbMetric;
+            pcb->m_Drawings.Append( gbritem );
+//            D( printf( "R:%p dcode %d layer %d\n", gbritem, dcode, activeLayer ); )
+            fillFlashedGBRITEM( gbritem, aperture,
+                                dcode, activeLayer, m_CurrentPos,
+                                size, m_LayerNegative, m_ImageNegative  );
             m_PreviousPos = m_CurrentPos;
             break;
 
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);