/******************************************************************************
**  libDXFrw - Library to read/write DXF files (ascii & binary)              **
**                                                                           **
**  Copyright (C) 2011 Rallaz, rallazz@gmail.com                             **
**                                                                           **
**  This library is free software, licensed under the terms of the GNU       **
**  General Public License as published by the Free Software Foundation,     **
**  either version 2 of the License, or (at your option) any later version.  **
**  You should have received a copy of the GNU General Public License        **
**  along with this program.  If not, see <http://www.gnu.org/licenses/>.    **
******************************************************************************/

#include <cstdlib>
#include "drw_entities.h"
#include "intern/dxfreader.h"


// ! Calculate arbitary axis
/*!
 *   Calculate arbitary axis for apply extrusions
 *  @author Rallaz
 */
void DRW_Entity::calculateAxis( DRW_Coord extPoint )
{
    // Follow the arbitrary DXF definitions for extrusion axes.
    if( fabs( extPoint.x ) < 0.015625 && fabs( extPoint.y ) < 0.015625 )
    {
        // If we get here, implement Ax = Wy x N where Wy is [0,1,0] per the DXF spec.
        // The cross product works out to Wy.y*N.z-Wy.z*N.y, Wy.z*N.x-Wy.x*N.z, Wy.x*N.y-Wy.y*N.x
        // Factoring in the fixed values for Wy gives N.z,0,-N.x
        extAxisX.x  = extPoint.z;
        extAxisX.y  = 0;
        extAxisX.z  = -extPoint.x;
    }
    else
    {
        // Otherwise, implement Ax = Wz x N where Wz is [0,0,1] per the DXF spec.
        // The cross product works out to Wz.y*N.z-Wz.z*N.y, Wz.z*N.x-Wz.x*N.z, Wz.x*N.y-Wz.y*N.x
        // Factoring in the fixed values for Wz gives -N.y,N.x,0.
        extAxisX.x  = -extPoint.y;
        extAxisX.y  = extPoint.x;
        extAxisX.z  = 0;
    }

    extAxisX.unitize();

    // Ay = N x Ax
    extAxisY.x  = (extPoint.y * extAxisX.z) - (extAxisX.y * extPoint.z);
    extAxisY.y  = (extPoint.z * extAxisX.x) - (extAxisX.z * extPoint.x);
    extAxisY.z  = (extPoint.x * extAxisX.y) - (extAxisX.x * extPoint.y);

    extAxisY.unitize();
}


// ! Extrude a point using arbitary axis
/*!
 *   apply extrusion in a point using arbitary axis (previous calculated)
 *  @author Rallaz
 */
void DRW_Entity::extrudePoint( DRW_Coord extPoint, DRW_Coord* point )
{
    double px, py, pz;

    px  = (extAxisX.x * point->x) + (extAxisY.x * point->y) + (extPoint.x * point->z);
    py  = (extAxisX.y * point->x) + (extAxisY.y * point->y) + (extPoint.y * point->z);
    pz  = (extAxisX.z * point->x) + (extAxisY.z * point->y) + (extPoint.z * point->z);

    point->x    = px;
    point->y    = py;
    point->z    = pz;
}


void DRW_Entity::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 5:
        handle = reader->getHandleString();
        break;

    case 330:
        handleBlock = reader->getHandleString();
        break;

    case 8:
        layer = reader->getUtf8String();
        break;

    case 6:
        lineType = reader->getUtf8String();
        break;

    case 62:
        color = reader->getInt32();
        break;

    case 370:
        lWeight = DRW_LW_Conv::dxfInt2lineWidth( reader->getInt32() );
        break;

    case 48:
        ltypeScale = reader->getDouble();
        break;

    case 60:
        visible = reader->getBool();
        break;

    case 420:
        color24 = reader->getInt32();
        break;

    case 430:
        colorName = reader->getString();
        break;

    case 67:
        space = reader->getInt32();
        break;

    case 1000:
    case 1001:
    case 1002:
    case 1003:
    case 1004:
    case 1005:
        extData.push_back( new DRW_Variant( code, reader->getString() ) );
        break;

    case 1010:
    case 1011:
    case 1012:
    case 1013:
        curr = new DRW_Variant();
        curr->addCoord();
        curr->setCoordX( reader->getDouble() );
        curr->code = code;
        extData.push_back( curr );
        break;

    case 1020:
    case 1021:
    case 1022:
    case 1023:

        if( curr )
            curr->setCoordY( reader->getDouble() );

        break;

    case 1030:
    case 1031:
    case 1032:
    case 1033:

        if( curr )
            curr->setCoordZ( reader->getDouble() );

        curr = NULL;
        break;

    case 1040:
    case 1041:
    case 1042:
        extData.push_back( new DRW_Variant( code, reader->getDouble() ) );
        break;

    case 1070:
    case 1071:
        extData.push_back( new DRW_Variant( code, reader->getInt32() ) );
        break;

    default:
        break;
    }
}


void DRW_Point::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 10:
        basePoint.x = reader->getDouble();
        break;

    case 20:
        basePoint.y = reader->getDouble();
        break;

    case 30:
        basePoint.z = reader->getDouble();
        break;

    case 39:
        thickness = reader->getDouble();
        break;

    case 210:
        haveExtrusion = true;
        extPoint.x = reader->getDouble();
        break;

    case 220:
        extPoint.y = reader->getDouble();
        break;

    case 230:
        extPoint.z = reader->getDouble();
        break;

    default:
        DRW_Entity::parseCode( code, reader );
        break;
    }
}


void DRW_Line::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 11:
        secPoint.x = reader->getDouble();
        break;

    case 21:
        secPoint.y = reader->getDouble();
        break;

    case 31:
        secPoint.z = reader->getDouble();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}


void DRW_Circle::applyExtrusion()
{
    if( haveExtrusion )
    {
        // NOTE: Commenting these out causes the the arcs being tested to be located
        // on the other side of the y axis (all x dimensions are negated).
        calculateAxis( extPoint );
        extrudePoint( extPoint, &basePoint );
    }
}


void DRW_Circle::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 40:
        radious = reader->getDouble();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}


void DRW_Arc::applyExtrusion()
{
    DRW_Circle::applyExtrusion();

    if( haveExtrusion )
    {
        // If the extrusion vector has a z value less than 0, the angles for the arc
        // have to be mirrored since DXF files use the right hand rule.
        // Note that the following code only handles the special case where there is a 2D
        // drawing with the z axis heading into the paper (or rather screen). An arbitrary
        // extrusion axis (with x and y values greater than 1/64) may still have issues.
        if( fabs( extPoint.x ) < 0.015625 && fabs( extPoint.y ) < 0.015625 && extPoint.z < 0.0 )
        {
            staangle    = M_PI - staangle;
            endangle    = M_PI - endangle;

            double temp = staangle;
            staangle    = endangle;
            endangle    = temp;
        }
    }
}


void DRW_Arc::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 50:
        staangle = reader->getDouble() / ARAD;
        break;

    case 51:
        endangle = reader->getDouble() / ARAD;
        break;

    default:
        DRW_Circle::parseCode( code, reader );
        break;
    }
}


void DRW_Ellipse::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 40:
        ratio = reader->getDouble();
        break;

    case 41:
        staparam = reader->getDouble();
        break;

    case 42:
        endparam = reader->getDouble();
        break;

    default:
        DRW_Line::parseCode( code, reader );
        break;
    }
}


void DRW_Ellipse::applyExtrusion()
{
    if( haveExtrusion )
    {
        calculateAxis( extPoint );
        extrudePoint( extPoint, &secPoint );
        double intialparam = staparam;

        if( extPoint.z < 0. )
        {
            staparam    = M_PIx2 - endparam;
            endparam    = M_PIx2 - intialparam;
        }
    }
}


// if ratio > 1 minor axis are greather than major axis, correct it
void DRW_Ellipse::correctAxis()
{
    bool complete = false;

    if( staparam == endparam )
    {
        staparam    = 0.0;
        endparam    = M_PIx2; // 2*M_PI;
        complete    = true;
    }

    if( ratio > 1 )
    {
        if( fabs( endparam - staparam - M_PIx2 ) < 1.0e-10 )
            complete = true;

        double incX = secPoint.x;
        secPoint.x  = -(secPoint.y * ratio);
        secPoint.y  = incX * ratio;
        ratio = 1 / ratio;

        if( !complete )
        {
            if( staparam < M_PI_2 )
                staparam += M_PI * 2;

            if( endparam < M_PI_2 )
                endparam += M_PI * 2;

            endparam    -= M_PI_2;
            staparam    -= M_PI_2;
        }
    }
}


// parts are the number of vertex to split polyline, default 128
void DRW_Ellipse::toPolyline( DRW_Polyline* pol, int parts )
{
    double  radMajor, radMinor, cosRot, sinRot, incAngle, curAngle;
    double  cosCurr, sinCurr;

    radMajor    = sqrt( secPoint.x * secPoint.x + secPoint.y * secPoint.y );
    radMinor    = radMajor * ratio;
    // calculate sin & cos of included angle
    incAngle = atan2( secPoint.y, secPoint.x );
    cosRot  = cos( incAngle );
    sinRot  = sin( incAngle );
    incAngle    = M_PIx2 / parts;
    curAngle    = staparam;
    int i = curAngle / incAngle;

    do {
        if( curAngle > endparam )
        {
            curAngle = endparam;
            i = parts + 2;
        }

        cosCurr = cos( curAngle );
        sinCurr = sin( curAngle );
        double  x   = basePoint.x + (cosCurr * cosRot * radMajor) - (sinCurr * sinRot * radMinor);
        double  y   = basePoint.y + (cosCurr * sinRot * radMajor) + (sinCurr * cosRot * radMinor);
        pol->addVertex( DRW_Vertex( x, y, 0.0, 0.0 ) );
        curAngle = (++i) * incAngle;
    } while( i<parts );

    if( fabs( endparam - staparam - M_PIx2 ) < 1.0e-10 )
    {
        pol->flags = 1;
    }

    pol->layer = this->layer;
    pol->lineType = this->lineType;
    pol->color = this->color;
    pol->lWeight    = this->lWeight;
    pol->extPoint   = this->extPoint;
}


void DRW_Trace::applyExtrusion()
{
    if( haveExtrusion )
    {
        calculateAxis( extPoint );
        extrudePoint( extPoint, &basePoint );
        extrudePoint( extPoint, &secPoint );
        extrudePoint( extPoint, &thirdPoint );
        extrudePoint( extPoint, &fourPoint );
    }
}


void DRW_Trace::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 12:
        thirdPoint.x = reader->getDouble();
        break;

    case 22:
        thirdPoint.y = reader->getDouble();
        break;

    case 32:
        thirdPoint.z = reader->getDouble();
        break;

    case 13:
        fourPoint.x = reader->getDouble();
        break;

    case 23:
        fourPoint.y = reader->getDouble();
        break;

    case 33:
        fourPoint.z = reader->getDouble();
        break;

    default:
        DRW_Line::parseCode( code, reader );
        break;
    }
}


void DRW_Solid::parseCode( int code, dxfReader* reader )
{
    DRW_Trace::parseCode( code, reader );
}


void DRW_3Dface::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 70:
        invisibleflag = reader->getInt32();
        break;

    default:
        DRW_Trace::parseCode( code, reader );
        break;
    }
}


void DRW_Block::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 2:
        name = reader->getUtf8String();
        break;

    case 70:
        flags = reader->getInt32();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}


void DRW_Insert::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 2:
        name = reader->getUtf8String();
        break;

    case 41:
        xscale = reader->getDouble();
        break;

    case 42:
        yscale = reader->getDouble();
        break;

    case 43:
        zscale = reader->getDouble();
        break;

    case 50:
        angle = reader->getDouble();
        break;

    case 70:
        colcount = reader->getInt32();
        break;

    case 71:
        rowcount = reader->getInt32();
        break;

    case 44:
        colspace = reader->getDouble();
        break;

    case 45:
        rowspace = reader->getDouble();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}


void DRW_LWPolyline::applyExtrusion()
{
    if( haveExtrusion )
    {
        calculateAxis( extPoint );

        for( unsigned int i = 0; i<vertlist.size(); i++ )
        {
            DRW_Vertex2D* vert = vertlist.at( i );
            DRW_Coord v( vert->x, vert->y, elevation );
            extrudePoint( extPoint, &v );
            vert->x = v.x;
            vert->y = v.y;
        }
    }
}


void DRW_LWPolyline::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 10:
    {
        vertex = new DRW_Vertex2D();
        vertlist.push_back( vertex );
        vertex->x = reader->getDouble();
        break;
    }

    case 20:

        if( vertex != NULL )
            vertex->y = reader->getDouble();

        break;

    case 40:

        if( vertex != NULL )
            vertex->stawidth = reader->getDouble();

        break;

    case 41:

        if( vertex != NULL )
            vertex->endwidth = reader->getDouble();

        break;

    case 42:

        if( vertex != NULL )
            vertex->bulge = reader->getDouble();

        break;

    case 38:
        elevation = reader->getDouble();
        break;

    case 39:
        thickness = reader->getDouble();
        break;

    case 43:
        width = reader->getDouble();
        break;

    case 70:
        flags = reader->getInt32();
        break;

    case 90:
        vertexnum = reader->getInt32();
        vertlist.reserve( vertexnum );
        break;

    case 210:
        haveExtrusion = true;
        extPoint.x = reader->getDouble();
        break;

    case 220:
        extPoint.y = reader->getDouble();
        break;

    case 230:
        extPoint.z = reader->getDouble();
        break;

    default:
        DRW_Entity::parseCode( code, reader );
        break;
    }
}


void DRW_Text::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 40:
        height = reader->getDouble();
        break;

    case 41:
        widthscale = reader->getDouble();
        break;

    case 50:
        angle = reader->getDouble();
        break;

    case 51:
        oblique = reader->getDouble();
        break;

    case 71:
        textgen = reader->getInt32();
        break;

    case 72:
        alignH = (HAlign) reader->getInt32();
        break;

    case 73:
        alignV = (VAlign) reader->getInt32();
        break;

    case 1:
        text = reader->getUtf8String();
        break;

    case 7:
        style = reader->getUtf8String();
        break;

    default:
        DRW_Line::parseCode( code, reader );
        break;
    }
}


void DRW_MText::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 1:
        text    += reader->getString();
        text    = reader->toUtf8String( text );
        break;

    case 11:
        haveXAxis = true;
        DRW_Text::parseCode( code, reader );
        break;

    case 3:
        text += reader->getString();
        break;

    case 44:
        interlin = reader->getDouble();
        break;

    default:
        DRW_Text::parseCode( code, reader );
        break;
    }
}


void DRW_MText::updateAngle()
{
    if( haveXAxis )
    {
        angle = atan2( secPoint.y, secPoint.x ) * 180 / M_PI;
    }
}


void DRW_Polyline::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 70:
        flags = reader->getInt32();
        break;

    case 40:
        defstawidth = reader->getDouble();
        break;

    case 41:
        defendwidth = reader->getDouble();
        break;

    case 71:
        vertexcount = reader->getInt32();
        break;

    case 72:
        facecount = reader->getInt32();
        break;

    case 73:
        smoothM = reader->getInt32();
        break;

    case 74:
        smoothN = reader->getInt32();
        break;

    case 75:
        curvetype = reader->getInt32();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}


void DRW_Vertex::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 70:
        flags = reader->getInt32();
        break;

    case 40:
        stawidth = reader->getDouble();
        break;

    case 41:
        endwidth = reader->getDouble();
        break;

    case 42:
        bulge = reader->getDouble();
        break;

    case 50:
        tgdir = reader->getDouble();
        break;

    case 71:
        vindex1 = reader->getInt32();
        break;

    case 72:
        vindex2 = reader->getInt32();
        break;

    case 73:
        vindex3 = reader->getInt32();
        break;

    case 74:
        vindex4 = reader->getInt32();
        break;

    case 91:
        identifier = reader->getInt32();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}


void DRW_Hatch::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 2:
        name = reader->getUtf8String();
        break;

    case 70:
        solid = reader->getInt32();
        break;

    case 71:
        associative = reader->getInt32();
        break;

    case 72:        /*edge type*/

        if( ispol ) // if is polyline is a as_bulge flag
        {
            break;
        }
        else if( reader->getInt32() == 1 )    // line
        {
            addLine();
        }
        else if( reader->getInt32() == 2 )    // arc
        {
            addArc();
        }
        else if( reader->getInt32() == 3 )    // elliptic arc
        {
            addEllipse();
        }
        else if( reader->getInt32() == 4 )    // spline
        {
            addSpline();
        }

        break;

    case 10:

        if( pt )
            pt->basePoint.x = reader->getDouble();
        else if( pline )
        {
            plvert = pline->addVertex();
            plvert->x = reader->getDouble();
        }

        break;

    case 20:

        if( pt )
            pt->basePoint.y = reader->getDouble();
        else if( plvert )
            plvert->y = reader->getDouble();

        break;

    case 11:

        if( line )
            line->secPoint.x = reader->getDouble();
        else if( ellipse )
            ellipse->secPoint.x = reader->getDouble();

        break;

    case 21:

        if( line )
            line->secPoint.y = reader->getDouble();
        else if( ellipse )
            ellipse->secPoint.y = reader->getDouble();

        break;

    case 40:

        if( arc )
            arc->radious = reader->getDouble();
        else if( ellipse )
            ellipse->ratio = reader->getDouble();

        break;

    case 41:
        scale = reader->getDouble();
        break;

    case 42:

        if( plvert )
            plvert->bulge = reader->getDouble();

        break;

    case 50:

        if( arc )
            arc->staangle = reader->getDouble() / ARAD;
        else if( ellipse )
            ellipse->staparam = reader->getDouble() / ARAD;

        break;

    case 51:

        if( arc )
            arc->endangle = reader->getDouble() / ARAD;
        else if( ellipse )
            ellipse->endparam = reader->getDouble() / ARAD;

        break;

    case 52:
        angle = reader->getDouble();
        break;

    case 73:

        if( arc )
            arc->isccw = reader->getInt32();
        else if( pline )
            pline->flags = reader->getInt32();

        break;

    case 75:
        hstyle = reader->getInt32();
        break;

    case 76:
        hpattern = reader->getInt32();
        break;

    case 77:
        doubleflag = reader->getInt32();
        break;

    case 78:
        deflines = reader->getInt32();
        break;

    case 91:
        loopsnum = reader->getInt32();
        looplist.reserve( loopsnum );
        break;

    case 92:
        loop = new DRW_HatchLoop( reader->getInt32() );
        looplist.push_back( loop );

        if( reader->getInt32() & 2 )
        {
            ispol = true;
            clearEntities();
            pline = new DRW_LWPolyline;
            loop->objlist.push_back( pline );
        }
        else
            ispol = false;

        break;

    case 93:

        if( pline )
            pline->vertexnum = reader->getInt32();
        else
            loop->numedges = reader->getInt32(); // aqui reserve

        break;

    case 98:    // seed points ??
        clearEntities();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}


void DRW_Spline::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 210:
        ex = reader->getDouble();
        break;

    case 220:
        ey = reader->getDouble();
        break;

    case 230:
        ez = reader->getDouble();
        break;

    case 12:
        tgsx = reader->getDouble();
        break;

    case 22:
        tgsy = reader->getDouble();
        break;

    case 32:
        tgsz = reader->getDouble();
        break;

    case 13:
        tgex = reader->getDouble();
        break;

    case 23:
        tgey = reader->getDouble();
        break;

    case 33:
        tgez = reader->getDouble();
        break;

    case 70:
        flags = reader->getInt32();
        break;

    case 71:
        degree = reader->getInt32();
        break;

    case 72:
        nknots = reader->getInt32();
        break;

    case 73:
        ncontrol = reader->getInt32();
        break;

    case 74:
        nfit = reader->getInt32();
        break;

    case 42:
        tolknot = reader->getDouble();
        break;

    case 43:
        tolcontrol = reader->getDouble();
        break;

    case 44:
        tolfit = reader->getDouble();
        break;

    case 10:
    {
        controlpoint = new DRW_Coord();
        controllist.push_back( controlpoint );
        controlpoint->x = reader->getDouble();
        break;
    }

    case 20:

        if( controlpoint != NULL )
            controlpoint->y = reader->getDouble();

        break;

    case 30:

        if( controlpoint != NULL )
            controlpoint->z = reader->getDouble();

        break;

    case 11:
    {
        fitpoint = new DRW_Coord();
        fitlist.push_back( fitpoint );
        fitpoint->x = reader->getDouble();
        break;
    }

    case 21:

        if( fitpoint != NULL )
            fitpoint->y = reader->getDouble();

        break;

    case 31:

        if( fitpoint != NULL )
            fitpoint->z = reader->getDouble();

        break;

    case 40:
        knotslist.push_back( reader->getDouble() );
        break;

// case 41:
// break;
    default:
        DRW_Entity::parseCode( code, reader );
        break;
    }
}


void DRW_Image::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 12:
        vx = reader->getDouble();
        break;

    case 22:
        vy = reader->getDouble();
        break;

    case 32:
        vz = reader->getDouble();
        break;

    case 13:
        sizeu = reader->getDouble();
        break;

    case 23:
        sizev = reader->getDouble();
        break;

    case 340:
        ref = reader->getString();
        break;

    case 280:
        clip = reader->getInt32();
        break;

    case 281:
        brightness = reader->getInt32();
        break;

    case 282:
        contrast = reader->getInt32();
        break;

    case 283:
        fade = reader->getInt32();
        break;

    default:
        DRW_Line::parseCode( code, reader );
        break;
    }
}


void DRW_Dimension::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 1:
        text = reader->getUtf8String();
        break;

    case 2:
        name = reader->getString();
        break;

    case 3:
        style = reader->getUtf8String();
        break;

    case 70:
        type = reader->getInt32();
        break;

    case 71:
        align = reader->getInt32();
        break;

    case 72:
        linesty = reader->getInt32();
        break;

    case 10:
        defPoint.x = reader->getDouble();
        break;

    case 20:
        defPoint.y = reader->getDouble();
        break;

    case 30:
        defPoint.z = reader->getDouble();
        break;

    case 11:
        textPoint.x = reader->getDouble();
        break;

    case 21:
        textPoint.y = reader->getDouble();
        break;

    case 31:
        textPoint.z = reader->getDouble();
        break;

    case 12:
        clonePoint.x = reader->getDouble();
        break;

    case 22:
        clonePoint.y = reader->getDouble();
        break;

    case 32:
        clonePoint.z = reader->getDouble();
        break;

    case 13:
        def1.x = reader->getDouble();
        break;

    case 23:
        def1.y = reader->getDouble();
        break;

    case 33:
        def1.z = reader->getDouble();
        break;

    case 14:
        def2.x = reader->getDouble();
        break;

    case 24:
        def2.y = reader->getDouble();
        break;

    case 34:
        def2.z = reader->getDouble();
        break;

    case 15:
        circlePoint.x = reader->getDouble();
        break;

    case 25:
        circlePoint.y = reader->getDouble();
        break;

    case 35:
        circlePoint.z = reader->getDouble();
        break;

    case 16:
        arcPoint.x = reader->getDouble();
        break;

    case 26:
        arcPoint.y = reader->getDouble();
        break;

    case 36:
        arcPoint.z = reader->getDouble();
        break;

    case 41:
        linefactor = reader->getDouble();
        break;

    case 53:
        rot = reader->getDouble();
        break;

    case 50:
        angle = reader->getDouble();
        break;

    case 52:
        oblique = reader->getDouble();
        break;

    case 40:
        length = reader->getDouble();
        break;

/*    case 51:
 *       hdir = reader->getDouble();
 *       break;*/
    default:
        DRW_Entity::parseCode( code, reader );
        break;
    }
}


void DRW_Leader::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 3:
        style = reader->getUtf8String();
        break;

    case 71:
        arrow = reader->getInt32();
        break;

    case 72:
        leadertype = reader->getInt32();
        break;

    case 73:
        flag = reader->getInt32();
        break;

    case 74:
        hookline = reader->getInt32();
        break;

    case 75:
        hookflag = reader->getInt32();
        break;

    case 76:
        vertnum = reader->getInt32();
        break;

    case 77:
        coloruse = reader->getInt32();
        break;

    case 40:
        textheight = reader->getDouble();
        break;

    case 41:
        textwidth = reader->getDouble();
        break;

    case 10:
    {
        vertexpoint = new DRW_Coord();
        vertexlist.push_back( vertexpoint );
        vertexpoint->x = reader->getDouble();
        break;
    }

    case 20:

        if( vertexpoint != NULL )
            vertexpoint->y = reader->getDouble();

        break;

    case 30:

        if( vertexpoint != NULL )
            vertexpoint->z = reader->getDouble();

        break;

    case 340:
        handle = reader->getString();
        break;

    case 210:
        extrusionPoint.x = reader->getDouble();
        break;

    case 220:
        extrusionPoint.y = reader->getDouble();
        break;

    case 230:
        extrusionPoint.z = reader->getDouble();
        break;

    case 211:
        horizdir.x = reader->getDouble();
        break;

    case 221:
        horizdir.y = reader->getDouble();
        break;

    case 231:
        horizdir.z = reader->getDouble();
        break;

    case 212:
        offsetblock.x = reader->getDouble();
        break;

    case 222:
        offsetblock.y = reader->getDouble();
        break;

    case 232:
        offsetblock.z = reader->getDouble();
        break;

    case 213:
        offsettext.x = reader->getDouble();
        break;

    case 223:
        offsettext.y = reader->getDouble();
        break;

    case 233:
        offsettext.z = reader->getDouble();
        break;

    default:
        DRW_Entity::parseCode( code, reader );
        break;
    }
}


void DRW_Viewport::parseCode( int code, dxfReader* reader )
{
    switch( code )
    {
    case 40:
        pswidth = reader->getDouble();
        break;

    case 41:
        psheight = reader->getDouble();
        break;

    case 68:
        vpstatus = reader->getInt32();
        break;

    case 69:
        vpID = reader->getInt32();
        break;

    case 12:
    {
        centerPX = reader->getDouble();
        break;
    }

    case 22:
        centerPY = reader->getDouble();
        break;

    default:
        DRW_Point::parseCode( code, reader );
        break;
    }
}