void AM_PRIMITIVE::DrawBasicShape( const GERBER_DRAW_ITEM* aParent,
                                   SHAPE_POLY_SET& aShapeBuffer,
                                   wxPoint aShapePos )
{
    #define TO_POLY_SHAPE { aShapeBuffer.NewOutline(); \
                            for( unsigned jj = 0; jj < polybuffer.size(); jj++ )\
                                aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y );\
                            aShapeBuffer.Append( polybuffer[0].x, polybuffer[0].y );}

    // Draw the primitive shape for flashed items.
    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();
    double rotation;

    switch( primitive_id )
    {
    case AMP_CIRCLE:        // Circle, given diameter and position
    {
        /* Generated by an aperture macro declaration like:
         * "1,1,0.3,0.5, 1.0*"
         * type (1), exposure, diameter, pos.x, pos.y, <rotation>
         * <rotation> is a optional parameter: rotation from origin.
         * type is not stored in parameters list, so the first parameter is exposure
         */
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation (if any):
        if( params.size() >= 5 )
        {
            rotation = params[4].GetValue( tool ) * 10.0;

            if( rotation != 0)
            {
                for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
                    RotatePoint( &polybuffer[ii], -rotation );
            }
        }


        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        TO_POLY_SHAPE;
    }
    break;

    case AMP_LINE2:
    case AMP_LINE20:        // Line with rectangle ends. (Width, start and end pos + rotation)
    {
        /* Vector Line, Primitive Code 20.
         * A vector line is a rectangle defined by its line width, start and end points.
         * The line ends are rectangular.
        */
        /* Generated by an aperture macro declaration like:
         * "2,1,0.3,0,0, 0.5, 1.0,-135*"
         * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation:
        rotation = params[6].GetValue( tool ) * 10.0;

        if( rotation != 0)
        {
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
                RotatePoint( &polybuffer[ii], -rotation );
        }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        TO_POLY_SHAPE;
    }
    break;

    case AMP_LINE_CENTER:
    {
        /* Center Line, Primitive Code 21
         * A center line primitive is a rectangle defined by its width, height, and center point
         */
        /* Generated by an aperture macro declaration like:
         * "21,1,0.3,0.03,0,0,-135*"
         * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation:
        rotation = params[5].GetValue( tool ) * 10.0;

        if( rotation != 0 )
        {
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
                RotatePoint( &polybuffer[ii], -rotation );
        }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        TO_POLY_SHAPE;
    }
    break;

    case AMP_LINE_LOWER_LEFT:
    {
        /* Generated by an aperture macro declaration like:
         * "22,1,0.3,0.03,0,0,-135*"
         * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation:
        rotation = params[5].GetValue( tool ) * 10.0;
        if( rotation != 0)
        {
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
                RotatePoint( &polybuffer[ii], -rotation );
        }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        TO_POLY_SHAPE;
    }
    break;

    case AMP_THERMAL:
    {
        /* Generated by an aperture macro declaration like:
         * "7, 0,0,1.0,0.3,0.01,-13*"
         * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
         * type is not stored in parameters list, so the first parameter is center.x
         *
         * The thermal primitive is a ring (annulus) interrupted by four gaps. Exposure is always on.
         */
        std::vector<wxPoint> subshape_poly;
        curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric );
        ConvertShapeToPolygon( aParent, subshape_poly );

        // shape rotation:
        rotation = params[5].GetValue( tool ) * 10.0;

        // Because a thermal shape has 4 identical sub-shapes, only one is created in subshape_poly.
        // We must draw 4 sub-shapes rotated by 90 deg
        for( int ii = 0; ii < 4; ii++ )
        {
            polybuffer = subshape_poly;
            double sub_rotation = rotation + 900 * ii;

            for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
                RotatePoint( &polybuffer[jj], -sub_rotation );

            // Move to current position:
            for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
            {
                polybuffer[jj] += curPos;
                polybuffer[jj] = aParent->GetABPosition( polybuffer[jj] );
            }

            TO_POLY_SHAPE;
        }
    }
    break;

    case AMP_MOIRE:
    {
        /* Moir�, Primitive Code 6
         * The moir� primitive is a cross hair centered on concentric rings (annuli).
         * Exposure is always on.
         */
        curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
                         m_GerbMetric );

        /* Generated by an aperture macro declaration like:
         * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
         * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
         * type is not stored in parameters list, so the first parameter is pos.x
         */
        int outerDiam    = scaletoIU( params[2].GetValue( tool ), m_GerbMetric );
        int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric );
        int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric );
        int numCircles = KiROUND( params[5].GetValue( tool ) );

        // Draw circles:
        wxPoint center = aParent->GetABPosition( curPos );
        // adjust outerDiam by this on each nested circle
        int diamAdjust = (gap + penThickness) * 2;

        for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
        {
            if( outerDiam <= 0 )
                break;

            // Note: outerDiam is the outer diameter of the ring.
            // the ring graphic diameter is (outerDiam - penThickness)
            if( outerDiam <= penThickness )
            {   // No room to draw a ring (no room for the hole):
                // draw a circle instead (with no hole), with the right diameter
                TransformCircleToPolygon( aShapeBuffer, center,
                                          outerDiam / 2, seg_per_circle );
            }
            else
                TransformRingToPolygon( aShapeBuffer, center,
                                        (outerDiam - penThickness) / 2,
                                        seg_per_circle, penThickness );
        }

        // Draw the cross:
        ConvertShapeToPolygon( aParent, polybuffer );

        rotation = params[8].GetValue( tool ) * 10.0;
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            // shape rotation:
            RotatePoint( &polybuffer[ii], -rotation );
            // Move to current position:
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        TO_POLY_SHAPE;
    }
        break;

    case AMP_OUTLINE:
    {
        /* Outline, Primitive Code 4
         * An outline primitive is an area enclosed by an n-point polygon defined by its start point and n
         * subsequent points. The outline must be closed, i.e. the last point must be equal to the start
         * point. There must be at least one subsequent point (to close the outline).
         * The outline of the primitive is actually the contour (see 2.6) that consists of linear segments
         * only, so it must conform to all the requirements described for contours.
         * Warning: Make no mistake: n is the number of subsequent points, being the number of
         * vertices of the outline or one less than the number of coordinate pairs.
        */
        /* 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, ..., corner1.x, corner.1y, rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        // params[0] is the exposure and params[1] is the corners count after the first corner
        int numCorners = (int) params[1].GetValue( tool );
        // the shape rotation is the last param of list, after corners
        int last_prm = params.size() - 1;
        rotation  = params[last_prm].GetValue( tool ) * 10.0;
        wxPoint pos;

        // Read points.
        // Note: numCorners is the polygon corner count, following the first corner
        // * the polygon is always closed,
        // * therefore the last XY coordinate is the same as the first
        int prm_idx = 2;    //  params[2] is the first X coordinate
        for( int i = 0; i <= numCorners; ++i )
        {
            pos.x = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
            prm_idx++;
            pos.y = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
            prm_idx++;
            polybuffer.push_back(pos);

            // Guard: ensure prm_idx < last_prm
            // I saw malformed gerber files with numCorners = number
            // of coordinates instead of number of coordinates following the first point
            if( prm_idx >= last_prm )
                break;
        }
        // rotate polygon and move it to the actual position
        // shape rotation:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            RotatePoint( &polybuffer[ii], -rotation );
       }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        TO_POLY_SHAPE;
    }
        break;

    case AMP_POLYGON:
        /* Polygon, Primitive Code 5
         * A polygon primitive is a regular polygon defined by the number of vertices n, the center point
         * and the diameter of the circumscribed circle
        */
        /* 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 ), m_GerbMetric );
        // Creates the shape:
        ConvertShapeToPolygon( aParent, polybuffer );

        // rotate polygon and move it to the actual position
        rotation  = params[5].GetValue( tool ) * 10.0;
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            RotatePoint( &polybuffer[ii], -rotation );
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        TO_POLY_SHAPE;

        break;

    case AMP_EOF:
        // not yet supported, waiting for you.
        break;

    case AMP_UNKNOWN:
    default:
        DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
        break;
    }
}
示例#2
0
void D_CODE::DrawFlashedShape(  GERBER_DRAW_ITEM* aParent,
                                EDA_RECT* aClipBox, wxDC* aDC, COLOR4D aColor,
                                wxPoint aShapePos, bool aFilledShape )
{
    int radius;

    switch( m_Shape )
    {
    case APT_MACRO:
        GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor,
                                            aShapePos, aFilledShape);
        break;

    case APT_CIRCLE:
        radius = m_Size.x >> 1;
        if( !aFilledShape )
            GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, 0, aColor );
        else
            if( m_DrillShape == APT_DEF_NO_HOLE )
            {
                GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
                                radius, aColor );
            }
            else if( m_DrillShape == APT_DEF_ROUND_HOLE )    // round hole in shape
            {
                int width = (m_Size.x - m_Drill.x ) / 2;
                GRCircle( aClipBox, aDC,  aParent->GetABPosition(aShapePos),
                          radius - (width / 2), width, aColor );
            }
            else                            // rectangular hole
            {
                if( m_Polygon.OutlineCount() == 0 )
                    ConvertShapeToPolygon();

                DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
            }
        break;

    case APT_RECT:
    {
        wxPoint start;
        start.x = aShapePos.x - m_Size.x / 2;
        start.y = aShapePos.y - m_Size.y / 2;
        wxPoint end = start + m_Size;
        start = aParent->GetABPosition( start );
        end = aParent->GetABPosition( end );

        if( !aFilledShape )
        {
            GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor );
        }
        else if( m_DrillShape == APT_DEF_NO_HOLE )
        {
            GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor, aColor );
        }
        else
        {
            if( m_Polygon.OutlineCount() == 0 )
                ConvertShapeToPolygon();

            DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
        }
    }
    break;

    case APT_OVAL:
    {
        wxPoint start = aShapePos;
        wxPoint end   = aShapePos;

        if( m_Size.x > m_Size.y )   // horizontal oval
        {
            int delta = (m_Size.x - m_Size.y) / 2;
            start.x -= delta;
            end.x   += delta;
            radius   = m_Size.y;
        }
        else   // horizontal oval
        {
            int delta = (m_Size.y - m_Size.x) / 2;
            start.y -= delta;
            end.y   += delta;
            radius   = m_Size.x;
        }

        start = aParent->GetABPosition( start );
        end = aParent->GetABPosition( end );

        if( !aFilledShape )
        {
            GRCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor );
        }
        else if( m_DrillShape == APT_DEF_NO_HOLE )
        {
            GRFillCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor );
        }
        else
        {
            if( m_Polygon.OutlineCount() == 0 )
                ConvertShapeToPolygon();

            DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
        }
    }
    break;

    case APT_POLYGON:
        if( m_Polygon.OutlineCount() == 0 )
            ConvertShapeToPolygon();

        DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
        break;
    }
}
/**
 * Function DrawBasicShape
 * Draw the primitive shape for flashed items.
 */
void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
                                   EDA_RECT* aClipBox,
                                   wxDC* aDC,
                                   EDA_COLOR_T aColor, EDA_COLOR_T 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();
    double rotation;
    if( mapExposure( aParent ) == false )
    {
        EXCHG(aColor, aAltColor);
    }

    switch( primitive_id )
    {
    case AMP_CIRCLE:        // Circle, given diameter and position
    {
        /* Generated by an aperture macro declaration like:
         * "1,1,0.3,0.5, 1.0*"
         * type (1), exposure, diameter, pos.x, pos.y
         * type is not stored in parameters list, so the first parameter is exposure
         */
        curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric );
        curPos = aParent->GetABPosition( curPos );
        int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2;
        if( !aFilledShape )
            GRCircle( aClipBox, aDC, curPos, radius, 0, aColor );
        else
            GRFilledCircle( aClipBox, aDC, curPos, radius, aColor );
    }
    break;

    case AMP_LINE2:
    case AMP_LINE20:        // Line with rectangle ends. (Width, start and end pos + rotation)
    {
        /* Generated by an aperture macro declaration like:
         * "2,1,0.3,0,0, 0.5, 1.0,-135*"
         * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation:
        rotation = params[6].GetValue( tool ) * 10.0;
        if( rotation != 0)
        {
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
                RotatePoint( &polybuffer[ii], -rotation );
        }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        GRClosedPoly( aClipBox, aDC,
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
    }
    break;

    case AMP_LINE_CENTER:
    {
        /* Generated by an aperture macro declaration like:
         * "21,1,0.3,0.03,0,0,-135*"
         * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation:
        rotation = params[5].GetValue( tool ) * 10.0;
        if( rotation != 0 )
        {
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
                RotatePoint( &polybuffer[ii], -rotation );
        }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        GRClosedPoly( aClipBox, aDC,
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
    }
    break;

    case AMP_LINE_LOWER_LEFT:
    {
        /* Generated by an aperture macro declaration like:
         * "22,1,0.3,0.03,0,0,-135*"
         * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation:
        rotation = params[5].GetValue( tool ) * 10.0;
        if( rotation != 0)
        {
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
                RotatePoint( &polybuffer[ii], -rotation );
        }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        GRClosedPoly( aClipBox, aDC,
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
    }
    break;

    case AMP_THERMAL:
    {
        /* Generated by an aperture macro declaration like:
         * "7, 0,0,1.0,0.3,0.01,-13*"
         * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
         * type is not stored in parameters list, so the first parameter is center.x
         */
        curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric );
        ConvertShapeToPolygon( aParent, polybuffer );

        // shape rotation:
        rotation = params[5].GetValue( tool ) * 10.0;

        // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer.
        // We must draw 4 sub-shapes rotated by 90 deg
        std::vector<wxPoint> subshape_poly;
        for( int ii = 0; ii < 4; ii++ )
        {
            subshape_poly = polybuffer;
            double 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;
                subshape_poly[jj] = aParent->GetABPosition( subshape_poly[jj] );
            }

            GRClosedPoly( aClipBox, aDC,
                          subshape_poly.size(), &subshape_poly[0], true, aAltColor,
                          aAltColor );
        }
    }
    break;

    case AMP_MOIRE:     // A cross hair with n concentric circles
    {
        curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
                         m_GerbMetric );

        /* Generated by an aperture macro declaration like:
         * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
         * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
         * type is not stored in parameters list, so the first parameter is pos.x
         */
        int outerDiam    = scaletoIU( params[2].GetValue( tool ), m_GerbMetric );
        int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric );
        int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric );
        int numCircles = KiROUND( params[5].GetValue( tool ) );

        // Draw circles:
        wxPoint center = aParent->GetABPosition( curPos );
        // adjust outerDiam by this on each nested circle
        int diamAdjust = (gap + penThickness); //*2;     //Should we use * 2 ?
        for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
        {
            if( outerDiam <= 0 )
                break;
            if( !aFilledShape )
            {
                // draw the border of the pen's path using two circles, each as narrow as possible
                GRCircle( aClipBox, aDC, center, outerDiam / 2, 0, aColor );
                GRCircle( aClipBox, aDC, center, outerDiam / 2 - penThickness, 0, aColor );
            }
            else    // Filled mode
            {
                GRCircle( aClipBox, aDC, center,
                          (outerDiam - penThickness) / 2, penThickness, aColor );
            }
        }

        // Draw the cross:
        ConvertShapeToPolygon( aParent, polybuffer );

        rotation = params[8].GetValue( tool ) * 10.0;
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            // shape rotation:
            RotatePoint( &polybuffer[ii], -rotation );
            // Move to current position:
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        GRClosedPoly( aClipBox, aDC,
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
    }
    break;

    case AMP_OUTLINE:
    {
        /* Generated by an aperture macro declaration like:
         * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
         * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation
         * type is not stored in parameters list, so the first parameter is exposure
         */
        int numPoints = (int) params[1].GetValue( tool );
        rotation  = params[numPoints * 2 + 4].GetValue( tool ) * 10.0;
        wxPoint pos;
        // Read points. numPoints does not include the starting point, so add 1.
        for( int i = 0; i<numPoints + 1; ++i )
        {
            int jj = i * 2 + 2;
            pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric );
            pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric );
            polybuffer.push_back(pos);
        }
        // rotate polygon and move it to the actual position
        // shape rotation:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            RotatePoint( &polybuffer[ii], -rotation );
        }

        // Move to current position:
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }

        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 ), m_GerbMetric );
        // Creates the shape:
        ConvertShapeToPolygon( aParent, polybuffer );

        // rotate polygon and move it to the actual position
        rotation  = params[5].GetValue( tool ) * 10.0;
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
        {
            RotatePoint( &polybuffer[ii], -rotation );
            polybuffer[ii] += curPos;
            polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] );
        }
        GRClosedPoly( aClipBox, aDC,
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
        break;

    case AMP_EOF:
        // not yet supported, waiting for you.
        break;

    case AMP_UNKNOWN:
    default:
        DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
        break;
    }
}