summaryrefslogtreecommitdiff
path: root/lib_dxf/libdxfrw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib_dxf/libdxfrw.cpp')
-rw-r--r--lib_dxf/libdxfrw.cpp3985
1 files changed, 3985 insertions, 0 deletions
diff --git a/lib_dxf/libdxfrw.cpp b/lib_dxf/libdxfrw.cpp
new file mode 100644
index 0000000..adc8b61
--- /dev/null
+++ b/lib_dxf/libdxfrw.cpp
@@ -0,0 +1,3985 @@
+/******************************************************************************
+** 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 "libdxfrw.h"
+#include <fstream>
+#include <algorithm>
+#include <sstream>
+#include "intern/drw_textcodec.h"
+#include "intern/dxfreader.h"
+#include "intern/dxfwriter.h"
+#include <assert.h>
+
+#ifdef DRW_DBG
+#include <iostream> // for debug
+#define DBG( a ) std::cerr << a
+#else
+#define DBG( a )
+#endif
+
+#define FIRSTHANDLE 48
+
+/*enum sections {
+ * secUnknown,
+ * secHeader,
+ * secTables,
+ * secBlocks,
+ * secEntities,
+ * secObjects
+ * };*/
+
+dxfRW::dxfRW( const char* name )
+{
+ fileName = name;
+ reader = NULL;
+ writer = NULL;
+ applyExt = false;
+ elParts = 128; // parts munber when convert ellipse to polyline
+
+ version = DRW::UNKNOWNV;
+
+ binary = false;
+ iface = NULL;
+ entCount = 0;
+ wlayer0 = false;
+ dimstyleStd = false;
+ writingBlock = false;
+ currHandle = 0;
+}
+
+
+dxfRW::~dxfRW()
+{
+ if( reader != NULL )
+ delete reader;
+
+ if( writer != NULL )
+ delete writer;
+
+ for( std::vector<DRW_ImageDef*>::iterator it = imageDef.begin(); it!=imageDef.end(); ++it )
+ delete *it;
+
+ imageDef.clear();
+}
+
+
+bool dxfRW::read( DRW_Interface* interface_, bool ext )
+{
+ assert( fileName.empty() == false );
+ bool isOk = false;
+ applyExt = ext;
+ std::ifstream filestr;
+
+ if( interface_ == NULL )
+ return isOk;
+
+ DBG( "dxfRW::read 1def\n" );
+ filestr.open( fileName.c_str(), std::ios_base::in | std::ios::binary );
+
+ if( !filestr.is_open() )
+ return isOk;
+
+ if( !filestr.good() )
+ return isOk;
+
+ char line[22];
+ char line2[22] = "AutoCAD Binary DXF\r\n";
+ line2[20] = (char) 26;
+ line2[21] = '\0';
+ filestr.read( line, 22 );
+ filestr.close();
+ iface = interface_;
+ DBG( "dxfRW::read 2\n" );
+
+ if( strcmp( line, line2 ) == 0 )
+ {
+ filestr.open( fileName.c_str(), std::ios_base::in | std::ios::binary );
+ binary = true;
+ // skip sentinel
+ filestr.seekg( 22, std::ios::beg );
+ reader = new dxfReaderBinary( &filestr );
+ DBG( "dxfRW::read binary file\n" );
+ }
+ else
+ {
+ binary = false;
+ filestr.open( fileName.c_str(), std::ios_base::in );
+ reader = new dxfReaderAscii( &filestr );
+ }
+
+ isOk = processDxf();
+ filestr.close();
+ delete reader;
+ reader = NULL;
+ return isOk;
+}
+
+
+bool dxfRW::write( DRW_Interface* interface_, DRW::Version ver, bool bin )
+{
+ bool isOk = false;
+ std::ofstream filestr;
+
+ version = ver;
+ binary = bin;
+ iface = interface_;
+
+ if( binary )
+ {
+ filestr.open( fileName.c_str(), std::ios_base::out | std::ios::binary | std::ios::trunc );
+ // write sentinel
+ filestr << "AutoCAD Binary DXF\r\n" << (char) 26 << '\0';
+ writer = new dxfWriterBinary( &filestr );
+ DBG( "dxfRW::read binary file\n" );
+ }
+ else
+ {
+ filestr.open( fileName.c_str(), std::ios_base::out | std::ios::trunc );
+ writer = new dxfWriterAscii( &filestr );
+ std::string comm = std::string( "dxfrw " ) + std::string( DRW_VERSION );
+ writer->writeString( 999, comm );
+ }
+
+ DRW_Header header;
+ iface->writeHeader( header );
+ writer->writeString( 0, "SECTION" );
+ entCount = FIRSTHANDLE;
+ header.write( writer, version );
+ writer->writeString( 0, "ENDSEC" );
+ writer->writeString( 0, "SECTION" );
+ writer->writeString( 2, "CLASSES" );
+ writer->writeString( 0, "ENDSEC" );
+ writer->writeString( 0, "SECTION" );
+ writer->writeString( 2, "TABLES" );
+ writeTables();
+ writer->writeString( 0, "ENDSEC" );
+ writer->writeString( 0, "SECTION" );
+ writer->writeString( 2, "BLOCKS" );
+ writeBlocks();
+ writer->writeString( 0, "ENDSEC" );
+
+ writer->writeString( 0, "SECTION" );
+ writer->writeString( 2, "ENTITIES" );
+ iface->writeEntities();
+ writer->writeString( 0, "ENDSEC" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "SECTION" );
+ writer->writeString( 2, "OBJECTS" );
+ writeObjects();
+ writer->writeString( 0, "ENDSEC" );
+ }
+
+ writer->writeString( 0, "EOF" );
+ filestr.flush();
+ filestr.close();
+ isOk = true;
+ delete writer;
+ writer = NULL;
+ return isOk;
+}
+
+
+bool dxfRW::writeEntity( DRW_Entity* ent )
+{
+ ent->handle = ++entCount;
+ writer->writeString( 5, toHexStr( ent->handle ) );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ if( ent->space == 1 )
+ writer->writeInt16( 67, 1 );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeUtf8String( 8, ent->layer );
+ writer->writeUtf8String( 6, ent->lineType );
+ }
+ else
+ {
+ writer->writeUtf8Caps( 8, ent->layer );
+ writer->writeUtf8Caps( 6, ent->lineType );
+ }
+
+ writer->writeInt16( 62, ent->color );
+
+ if( version > DRW::AC1015 && ent->color24 >= 0 )
+ {
+ writer->writeInt32( 420, ent->color24 );
+ }
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeInt16( 370, DRW_LW_Conv::lineWidth2dxfInt( ent->lWeight ) );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeLineType( DRW_LType* ent )
+{
+ std::string strname = ent->name;
+
+ transform( strname.begin(), strname.end(), strname.begin(), ::toupper );
+
+// do not write linetypes handled by library
+ if( strname == "BYLAYER" || strname == "BYBLOCK" || strname == "CONTINUOUS" )
+ {
+ return true;
+ }
+
+ writer->writeString( 0, "LTYPE" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, toHexStr( ++entCount ) );
+
+ if( version > DRW::AC1012 )
+ {
+ writer->writeString( 330, "5" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbLinetypeTableRecord" );
+ writer->writeUtf8String( 2, ent->name );
+ }
+ else
+ writer->writeUtf8Caps( 2, ent->name );
+
+ writer->writeInt16( 70, ent->flags );
+ writer->writeUtf8String( 3, ent->desc );
+ ent->update();
+ writer->writeInt16( 72, 65 );
+ writer->writeInt16( 73, ent->size );
+ writer->writeDouble( 40, ent->length );
+
+ for( unsigned int i = 0; i< ent->path.size(); i++ )
+ {
+ writer->writeDouble( 49, ent->path.at( i ) );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeInt16( 74, 0 );
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeLayer( DRW_Layer* ent )
+{
+ writer->writeString( 0, "LAYER" );
+
+ if( !wlayer0 && ent->name == "0" )
+ {
+ wlayer0 = true;
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "10" );
+ }
+ }
+ else
+ {
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, toHexStr( ++entCount ) );
+ }
+ }
+
+ if( version > DRW::AC1012 )
+ {
+ writer->writeString( 330, "2" );
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbLayerTableRecord" );
+ writer->writeUtf8String( 2, ent->name );
+ }
+ else
+ {
+ writer->writeUtf8Caps( 2, ent->name );
+ }
+
+ writer->writeInt16( 70, ent->flags );
+ writer->writeInt16( 62, ent->color );
+
+ if( version > DRW::AC1015 && ent->color24 >= 0 )
+ {
+ writer->writeInt32( 420, ent->color24 );
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeUtf8String( 6, ent->lineType );
+
+ if( !ent->plotF )
+ writer->writeBool( 290, ent->plotF );
+
+ writer->writeInt16( 370, DRW_LW_Conv::lineWidth2dxfInt( ent->lWeight ) );
+ writer->writeString( 390, "F" );
+ }
+ else
+ writer->writeUtf8Caps( 6, ent->lineType );
+
+ if( !ent->extData.empty() )
+ {
+ writeExtData( ent->extData );
+ }
+
+// writer->writeString(347, "10012");
+ return true;
+}
+
+
+bool dxfRW::writeTextstyle( DRW_Textstyle* ent )
+{
+ writer->writeString( 0, "STYLE" );
+
+ if( !dimstyleStd )
+ {
+ // stringstream cause crash in OS/X, bug#3597944
+ std::string name = ent->name;
+ transform( name.begin(), name.end(), name.begin(), toupper );
+
+ if( name == "STANDARD" )
+ dimstyleStd = true;
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, toHexStr( ++entCount ) );
+ }
+
+ if( version > DRW::AC1012 )
+ {
+ writer->writeString( 330, "2" );
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbTextStyleTableRecord" );
+ writer->writeUtf8String( 2, ent->name );
+ }
+ else
+ {
+ writer->writeUtf8Caps( 2, ent->name );
+ }
+
+ writer->writeInt16( 70, ent->flags );
+ writer->writeDouble( 40, ent->height );
+ writer->writeDouble( 41, ent->width );
+ writer->writeDouble( 50, ent->oblique );
+ writer->writeInt16( 71, ent->genFlag );
+ writer->writeDouble( 42, ent->lastHeight );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeUtf8String( 3, ent->font );
+ writer->writeUtf8String( 4, ent->bigFont );
+
+ if( ent->fontFamily != 0 )
+ writer->writeInt32( 1071, ent->fontFamily );
+ }
+ else
+ {
+ writer->writeUtf8Caps( 3, ent->font );
+ writer->writeUtf8Caps( 4, ent->bigFont );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeVport( DRW_Vport* ent )
+{
+ if( !dimstyleStd )
+ {
+ ent->name = "*ACTIVE";
+ dimstyleStd = true;
+ }
+
+ writer->writeString( 0, "VPORT" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, toHexStr( ++entCount ) );
+
+ if( version > DRW::AC1012 )
+ writer->writeString( 330, "2" );
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbViewportTableRecord" );
+ writer->writeUtf8String( 2, ent->name );
+ }
+ else
+ writer->writeUtf8Caps( 2, ent->name );
+
+ writer->writeInt16( 70, ent->flags );
+ writer->writeDouble( 10, ent->lowerLeft.x );
+ writer->writeDouble( 20, ent->lowerLeft.y );
+ writer->writeDouble( 11, ent->UpperRight.x );
+ writer->writeDouble( 21, ent->UpperRight.y );
+ writer->writeDouble( 12, ent->center.x );
+ writer->writeDouble( 22, ent->center.y );
+ writer->writeDouble( 13, ent->snapBase.x );
+ writer->writeDouble( 23, ent->snapBase.y );
+ writer->writeDouble( 14, ent->snapSpacing.x );
+ writer->writeDouble( 24, ent->snapSpacing.y );
+ writer->writeDouble( 15, ent->gridSpacing.x );
+ writer->writeDouble( 25, ent->gridSpacing.y );
+ writer->writeDouble( 16, ent->viewDir.x );
+ writer->writeDouble( 26, ent->viewDir.y );
+ writer->writeDouble( 36, ent->viewDir.z );
+ writer->writeDouble( 17, ent->viewTarget.z );
+ writer->writeDouble( 27, ent->viewTarget.z );
+ writer->writeDouble( 37, ent->viewTarget.z );
+ writer->writeDouble( 40, ent->height );
+ writer->writeDouble( 41, ent->ratio );
+ writer->writeDouble( 42, ent->lensHeight );
+ writer->writeDouble( 43, ent->frontClip );
+ writer->writeDouble( 44, ent->backClip );
+ writer->writeDouble( 50, ent->snapAngle );
+ writer->writeDouble( 51, ent->twistAngle );
+ writer->writeInt16( 71, ent->viewMode );
+ writer->writeInt16( 72, ent->circleZoom );
+ writer->writeInt16( 73, ent->fastZoom );
+ writer->writeInt16( 74, ent->ucsIcon );
+ writer->writeInt16( 75, ent->snap );
+ writer->writeInt16( 76, ent->grid );
+ writer->writeInt16( 77, ent->snapStyle );
+ writer->writeInt16( 78, ent->snapIsopair );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeInt16( 281, 0 );
+ writer->writeInt16( 65, 1 );
+ writer->writeDouble( 110, 0.0 );
+ writer->writeDouble( 120, 0.0 );
+ writer->writeDouble( 130, 0.0 );
+ writer->writeDouble( 111, 1.0 );
+ writer->writeDouble( 121, 0.0 );
+ writer->writeDouble( 131, 0.0 );
+ writer->writeDouble( 112, 0.0 );
+ writer->writeDouble( 122, 1.0 );
+ writer->writeDouble( 132, 0.0 );
+ writer->writeInt16( 79, 0 );
+ writer->writeDouble( 146, 0.0 );
+
+ if( version > DRW::AC1018 )
+ {
+ writer->writeString( 348, "10020" );
+ writer->writeInt16( 60, ent->gridBehavior ); // v2007 undocummented see DRW_Vport class
+ writer->writeInt16( 61, 5 );
+ writer->writeBool( 292, 1 );
+ writer->writeInt16( 282, 1 );
+ writer->writeDouble( 141, 0.0 );
+ writer->writeDouble( 142, 0.0 );
+ writer->writeInt16( 63, 250 );
+ writer->writeInt32( 421, 3358443 );
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeDimstyle( DRW_Dimstyle* ent )
+{
+ writer->writeString( 0, "DIMSTYLE" );
+
+ if( !dimstyleStd )
+ {
+ std::string name = ent->name;
+ std::transform( name.begin(), name.end(), name.begin(), ::toupper );
+
+ if( name == "STANDARD" )
+ dimstyleStd = true;
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 105, toHexStr( ++entCount ) );
+ }
+
+ if( version > DRW::AC1012 )
+ {
+ writer->writeString( 330, "A" );
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbDimStyleTableRecord" );
+ writer->writeUtf8String( 2, ent->name );
+ }
+ else
+ writer->writeUtf8Caps( 2, ent->name );
+
+ writer->writeInt16( 70, ent->flags );
+
+ if( version == DRW::AC1009 || !( ent->dimpost.empty() ) )
+ writer->writeUtf8String( 3, ent->dimpost );
+
+ if( version == DRW::AC1009 || !( ent->dimapost.empty() ) )
+ writer->writeUtf8String( 4, ent->dimapost );
+
+ if( version == DRW::AC1009 || !( ent->dimblk.empty() ) )
+ writer->writeUtf8String( 5, ent->dimblk );
+
+ if( version == DRW::AC1009 || !( ent->dimblk1.empty() ) )
+ writer->writeUtf8String( 6, ent->dimblk1 );
+
+ if( version == DRW::AC1009 || !( ent->dimblk2.empty() ) )
+ writer->writeUtf8String( 7, ent->dimblk2 );
+
+ writer->writeDouble( 40, ent->dimscale );
+ writer->writeDouble( 41, ent->dimasz );
+ writer->writeDouble( 42, ent->dimexo );
+ writer->writeDouble( 43, ent->dimdli );
+ writer->writeDouble( 44, ent->dimexe );
+ writer->writeDouble( 45, ent->dimrnd );
+ writer->writeDouble( 46, ent->dimdle );
+ writer->writeDouble( 47, ent->dimtp );
+ writer->writeDouble( 48, ent->dimtm );
+ writer->writeDouble( 140, ent->dimtxt );
+ writer->writeDouble( 141, ent->dimcen );
+ writer->writeDouble( 142, ent->dimtsz );
+ writer->writeDouble( 143, ent->dimaltf );
+ writer->writeDouble( 144, ent->dimlfac );
+ writer->writeDouble( 145, ent->dimtvp );
+ writer->writeDouble( 146, ent->dimtfac );
+ writer->writeDouble( 147, ent->dimgap );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeDouble( 148, ent->dimaltrnd );
+ }
+
+ writer->writeInt16( 71, ent->dimtol );
+ writer->writeInt16( 72, ent->dimlim );
+ writer->writeInt16( 73, ent->dimtih );
+ writer->writeInt16( 74, ent->dimtoh );
+ writer->writeInt16( 75, ent->dimse1 );
+ writer->writeInt16( 76, ent->dimse2 );
+ writer->writeInt16( 77, ent->dimtad );
+ writer->writeInt16( 78, ent->dimzin );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeInt16( 79, ent->dimazin );
+ }
+
+ writer->writeInt16( 170, ent->dimalt );
+ writer->writeInt16( 171, ent->dimaltd );
+ writer->writeInt16( 172, ent->dimtofl );
+ writer->writeInt16( 173, ent->dimsah );
+ writer->writeInt16( 174, ent->dimtix );
+ writer->writeInt16( 175, ent->dimsoxd );
+ writer->writeInt16( 176, ent->dimclrd );
+ writer->writeInt16( 177, ent->dimclre );
+ writer->writeInt16( 178, ent->dimclrt );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeInt16( 179, ent->dimadec );
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ if( version < DRW::AC1015 )
+ writer->writeInt16( 270, ent->dimunit );
+
+ writer->writeInt16( 271, ent->dimdec );
+ writer->writeInt16( 272, ent->dimtdec );
+ writer->writeInt16( 273, ent->dimaltu );
+ writer->writeInt16( 274, ent->dimalttd );
+ writer->writeInt16( 275, ent->dimaunit );
+ }
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeInt16( 276, ent->dimfrac );
+ writer->writeInt16( 277, ent->dimlunit );
+ writer->writeInt16( 278, ent->dimdsep );
+ writer->writeInt16( 279, ent->dimtmove );
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeInt16( 280, ent->dimjust );
+ writer->writeInt16( 281, ent->dimsd1 );
+ writer->writeInt16( 282, ent->dimsd2 );
+ writer->writeInt16( 283, ent->dimtolj );
+ writer->writeInt16( 284, ent->dimtzin );
+ writer->writeInt16( 285, ent->dimaltz );
+ writer->writeInt16( 286, ent->dimaltttz );
+
+ if( version < DRW::AC1015 )
+ writer->writeInt16( 287, ent->dimfit );
+
+ writer->writeInt16( 288, ent->dimupt );
+ }
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeInt16( 289, ent->dimatfit );
+ }
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeUtf8String( 340, ent->dimtxsty );
+ }
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeUtf8String( 341, ent->dimldrblk );
+ writer->writeInt16( 371, ent->dimlwd );
+ writer->writeInt16( 372, ent->dimlwe );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeAppId( DRW_AppId* ent )
+{
+ writer->writeString( 0, "APPID" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, toHexStr( ++entCount ) );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "9" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbRegAppTableRecord" );
+ writer->writeUtf8String( 2, ent->name );
+ }
+ else
+ {
+ writer->writeUtf8Caps( 2, ent->name );
+ }
+
+ writer->writeInt16( 70, ent->flags );
+ return true;
+}
+
+
+bool dxfRW::writePoint( DRW_Point* ent )
+{
+ writer->writeString( 0, "POINT" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbPoint" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+
+ if( ent->basePoint.z != 0.0 )
+ {
+ writer->writeDouble( 30, ent->basePoint.z );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeLine( DRW_Line* ent )
+{
+ writer->writeString( 0, "LINE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbLine" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+
+ if( ent->basePoint.z != 0.0 || ent->secPoint.z != 0.0 )
+ {
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ writer->writeDouble( 31, ent->secPoint.z );
+ }
+ else
+ {
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeRay( DRW_Ray* ent )
+{
+ writer->writeString( 0, "RAY" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbRay" );
+ }
+
+ DRW_Coord crd = ent->secPoint;
+ crd.unitize();
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+
+ if( ent->basePoint.z != 0.0 || ent->secPoint.z != 0.0 )
+ {
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, crd.x );
+ writer->writeDouble( 21, crd.y );
+ writer->writeDouble( 31, crd.z );
+ }
+ else
+ {
+ writer->writeDouble( 11, crd.x );
+ writer->writeDouble( 21, crd.y );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeXline( DRW_Xline* ent )
+{
+ writer->writeString( 0, "XLINE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbXline" );
+ }
+
+ DRW_Coord crd = ent->secPoint;
+ crd.unitize();
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+
+ if( ent->basePoint.z != 0.0 || ent->secPoint.z != 0.0 )
+ {
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, crd.x );
+ writer->writeDouble( 21, crd.y );
+ writer->writeDouble( 31, crd.z );
+ }
+ else
+ {
+ writer->writeDouble( 11, crd.x );
+ writer->writeDouble( 21, crd.y );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeCircle( DRW_Circle* ent )
+{
+ writer->writeString( 0, "CIRCLE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbCircle" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+
+ if( ent->basePoint.z != 0.0 )
+ {
+ writer->writeDouble( 30, ent->basePoint.z );
+ }
+
+ writer->writeDouble( 40, ent->radious );
+ return true;
+}
+
+
+bool dxfRW::writeArc( DRW_Arc* ent )
+{
+ writer->writeString( 0, "ARC" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbCircle" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+
+ if( ent->basePoint.z != 0.0 )
+ {
+ writer->writeDouble( 30, ent->basePoint.z );
+ }
+
+ writer->writeDouble( 40, ent->radious );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbArc" );
+ }
+
+ writer->writeDouble( 50, ent->staangle * ARAD );
+ writer->writeDouble( 51, ent->endangle * ARAD );
+ return true;
+}
+
+
+bool dxfRW::writeEllipse( DRW_Ellipse* ent )
+{
+ // verify axis/ratio and params for full ellipse
+ ent->correctAxis();
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "ELLIPSE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbEllipse" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ writer->writeDouble( 31, ent->secPoint.z );
+ writer->writeDouble( 40, ent->ratio );
+ writer->writeDouble( 41, ent->staparam );
+ writer->writeDouble( 42, ent->endparam );
+ }
+ else
+ {
+ DRW_Polyline pol;
+ // RLZ: copy properties
+ ent->toPolyline( &pol, elParts );
+ writePolyline( &pol );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeTrace( DRW_Trace* ent )
+{
+ writer->writeString( 0, "TRACE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbTrace" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ writer->writeDouble( 31, ent->secPoint.z );
+ writer->writeDouble( 12, ent->thirdPoint.x );
+ writer->writeDouble( 22, ent->thirdPoint.y );
+ writer->writeDouble( 32, ent->thirdPoint.z );
+ writer->writeDouble( 13, ent->fourPoint.x );
+ writer->writeDouble( 23, ent->fourPoint.y );
+ writer->writeDouble( 33, ent->fourPoint.z );
+ return true;
+}
+
+
+bool dxfRW::writeSolid( DRW_Solid* ent )
+{
+ writer->writeString( 0, "SOLID" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbTrace" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ writer->writeDouble( 31, ent->secPoint.z );
+ writer->writeDouble( 12, ent->thirdPoint.x );
+ writer->writeDouble( 22, ent->thirdPoint.y );
+ writer->writeDouble( 32, ent->thirdPoint.z );
+ writer->writeDouble( 13, ent->fourPoint.x );
+ writer->writeDouble( 23, ent->fourPoint.y );
+ writer->writeDouble( 33, ent->fourPoint.z );
+ return true;
+}
+
+
+bool dxfRW::write3dface( DRW_3Dface* ent )
+{
+ writer->writeString( 0, "3DFACE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbFace" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ writer->writeDouble( 31, ent->secPoint.z );
+ writer->writeDouble( 12, ent->thirdPoint.x );
+ writer->writeDouble( 22, ent->thirdPoint.y );
+ writer->writeDouble( 32, ent->thirdPoint.z );
+ writer->writeDouble( 13, ent->fourPoint.x );
+ writer->writeDouble( 23, ent->fourPoint.y );
+ writer->writeDouble( 33, ent->fourPoint.z );
+ writer->writeInt16( 70, ent->invisibleflag );
+ return true;
+}
+
+
+bool dxfRW::writeLWPolyline( DRW_LWPolyline* ent )
+{
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "LWPOLYLINE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbPolyline" );
+ }
+
+ ent->vertexnum = ent->vertlist.size();
+ writer->writeInt32( 90, ent->vertexnum );
+ writer->writeInt16( 70, ent->flags );
+ writer->writeDouble( 43, ent->width );
+
+ if( ent->elevation != 0 )
+ writer->writeDouble( 38, ent->elevation );
+
+ if( ent->thickness != 0 )
+ writer->writeDouble( 39, ent->thickness );
+
+ for( int i = 0; i< ent->vertexnum; i++ )
+ {
+ DRW_Vertex2D* v = ent->vertlist.at( i );
+ writer->writeDouble( 10, v->x );
+ writer->writeDouble( 20, v->y );
+
+ if( v->stawidth != 0 )
+ writer->writeDouble( 40, v->stawidth );
+
+ if( v->endwidth != 0 )
+ writer->writeDouble( 41, v->endwidth );
+
+ if( v->bulge != 0 )
+ writer->writeDouble( 42, v->bulge );
+ }
+ }
+ else
+ {
+ // RLZ: TODO convert lwpolyline in polyline (not exist in acad 12)
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writePolyline( DRW_Polyline* ent )
+{
+ writer->writeString( 0, "POLYLINE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ if( ent->flags & 8 || ent->flags & 16 )
+ writer->writeString( 100, "AcDb2dPolyline" );
+ else
+ writer->writeString( 100, "AcDb3dPolyline" );
+ }
+ else
+ writer->writeInt16( 66, 1 );
+
+ writer->writeDouble( 10, 0.0 );
+ writer->writeDouble( 20, 0.0 );
+ writer->writeDouble( 30, ent->basePoint.z );
+
+ if( ent->thickness != 0 )
+ {
+ writer->writeDouble( 39, ent->thickness );
+ }
+
+ writer->writeInt16( 70, ent->flags );
+
+ if( ent->defstawidth != 0 )
+ {
+ writer->writeDouble( 40, ent->defstawidth );
+ }
+
+ if( ent->defendwidth != 0 )
+ {
+ writer->writeDouble( 41, ent->defendwidth );
+ }
+
+ if( ent->flags & 16 || ent->flags & 32 )
+ {
+ writer->writeInt16( 71, ent->vertexcount );
+ writer->writeInt16( 72, ent->facecount );
+ }
+
+ if( ent->smoothM != 0 )
+ {
+ writer->writeInt16( 73, ent->smoothM );
+ }
+
+ if( ent->smoothN != 0 )
+ {
+ writer->writeInt16( 74, ent->smoothN );
+ }
+
+ if( ent->curvetype != 0 )
+ {
+ writer->writeInt16( 75, ent->curvetype );
+ }
+
+ DRW_Coord crd = ent->extPoint;
+
+ if( crd.x != 0 || crd.y != 0 || crd.z != 1 )
+ {
+ writer->writeDouble( 210, crd.x );
+ writer->writeDouble( 220, crd.y );
+ writer->writeDouble( 230, crd.z );
+ }
+
+ int vertexnum = ent->vertlist.size();
+
+ for( int i = 0; i< vertexnum; i++ )
+ {
+ DRW_Vertex* v = ent->vertlist.at( i );
+ writer->writeString( 0, "VERTEX" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ writer->writeString( 100, "AcDbVertex" );
+
+ if( (v->flags & 128) && !(v->flags & 64) )
+ {
+ writer->writeDouble( 10, 0 );
+ writer->writeDouble( 20, 0 );
+ writer->writeDouble( 30, 0 );
+ }
+ else
+ {
+ writer->writeDouble( 10, v->basePoint.x );
+ writer->writeDouble( 20, v->basePoint.y );
+ writer->writeDouble( 30, v->basePoint.z );
+ }
+
+ if( v->stawidth != 0 )
+ writer->writeDouble( 40, v->stawidth );
+
+ if( v->endwidth != 0 )
+ writer->writeDouble( 41, v->endwidth );
+
+ if( v->bulge != 0 )
+ writer->writeDouble( 42, v->bulge );
+
+ if( v->flags != 0 )
+ {
+ writer->writeInt16( 70, ent->flags );
+ }
+
+ if( v->flags & 2 )
+ {
+ writer->writeDouble( 50, v->tgdir );
+ }
+
+ if( v->flags & 128 )
+ {
+ if( v->vindex1 != 0 )
+ {
+ writer->writeInt16( 71, v->vindex1 );
+ }
+
+ if( v->vindex2 != 0 )
+ {
+ writer->writeInt16( 72, v->vindex2 );
+ }
+
+ if( v->vindex3 != 0 )
+ {
+ writer->writeInt16( 73, v->vindex3 );
+ }
+
+ if( v->vindex4 != 0 )
+ {
+ writer->writeInt16( 74, v->vindex4 );
+ }
+
+ if( !(v->flags & 64) )
+ {
+ writer->writeInt32( 91, v->identifier );
+ }
+ }
+ }
+
+ writer->writeString( 0, "SEQEND" );
+ writeEntity( ent );
+ return true;
+}
+
+
+bool dxfRW::writeSpline( DRW_Spline* ent )
+{
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "SPLINE" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbSpline" );
+ }
+
+ writer->writeDouble( 210, ent->ex );
+ writer->writeDouble( 220, ent->ey );
+ writer->writeDouble( 230, ent->ez );
+ writer->writeInt16( 70, ent->flags );
+ writer->writeInt16( 71, ent->degree );
+ writer->writeInt16( 72, ent->nknots );
+ writer->writeInt16( 73, ent->ncontrol );
+ writer->writeInt16( 74, ent->nfit );
+ writer->writeDouble( 42, ent->tolknot );
+ writer->writeDouble( 43, ent->tolcontrol );
+
+ // RLZ: warning check if nknots are correct and ncontrol
+ for( int i = 0; i< ent->nknots; i++ )
+ {
+ writer->writeDouble( 40, ent->knotslist.at( i ) );
+ }
+
+ for( int i = 0; i< ent->ncontrol; i++ )
+ {
+ DRW_Coord* crd = ent->controllist.at( i );
+ writer->writeDouble( 10, crd->x );
+ writer->writeDouble( 20, crd->y );
+ writer->writeDouble( 30, crd->z );
+ }
+ }
+ else
+ {
+ // RLZ: TODO convert spline in polyline (not exist in acad 12)
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeHatch( DRW_Hatch* ent )
+{
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "HATCH" );
+ writeEntity( ent );
+ writer->writeString( 100, "AcDbHatch" );
+ writer->writeDouble( 10, 0.0 );
+ writer->writeDouble( 20, 0.0 );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 210, ent->extPoint.x );
+ writer->writeDouble( 220, ent->extPoint.y );
+ writer->writeDouble( 230, ent->extPoint.z );
+ writer->writeString( 2, ent->name );
+ writer->writeInt16( 70, ent->solid );
+ writer->writeInt16( 71, ent->associative );
+ ent->loopsnum = ent->looplist.size();
+ writer->writeInt16( 91, ent->loopsnum );
+
+ // write paths data
+ for( int i = 0; i< ent->loopsnum; i++ )
+ {
+ DRW_HatchLoop* loop = ent->looplist.at( i );
+ writer->writeInt16( 92, loop->type );
+
+ if( (loop->type & 2) == 2 )
+ {
+ // RLZ: polyline boundary writeme
+ }
+ else
+ {
+ // boundary path
+ loop->update();
+ writer->writeInt16( 93, loop->numedges );
+
+ for( int j = 0; j<loop->numedges; ++j )
+ {
+ switch( ( loop->objlist.at( j ) )->eType )
+ {
+ case DRW::LINE:
+ {
+ writer->writeInt16( 72, 1 );
+ DRW_Line* l = (DRW_Line*) loop->objlist.at( j );
+ writer->writeDouble( 10, l->basePoint.x );
+ writer->writeDouble( 20, l->basePoint.y );
+ writer->writeDouble( 11, l->secPoint.x );
+ writer->writeDouble( 21, l->secPoint.y );
+ break;
+ }
+
+ case DRW::ARC:
+ {
+ writer->writeInt16( 72, 2 );
+ DRW_Arc* a = (DRW_Arc*) loop->objlist.at( j );
+ writer->writeDouble( 10, a->basePoint.x );
+ writer->writeDouble( 20, a->basePoint.y );
+ writer->writeDouble( 40, a->radious );
+ writer->writeDouble( 50, a->staangle * ARAD );
+ writer->writeDouble( 51, a->endangle * ARAD );
+ writer->writeInt16( 73, a->isccw );
+ break;
+ }
+
+ case DRW::ELLIPSE:
+ {
+ writer->writeInt16( 72, 3 );
+ DRW_Ellipse* a = (DRW_Ellipse*) loop->objlist.at( j );
+ a->correctAxis();
+ writer->writeDouble( 10, a->basePoint.x );
+ writer->writeDouble( 20, a->basePoint.y );
+ writer->writeDouble( 11, a->secPoint.x );
+ writer->writeDouble( 21, a->secPoint.y );
+ writer->writeDouble( 40, a->ratio );
+ writer->writeDouble( 50, a->staparam * ARAD );
+ writer->writeDouble( 51, a->endparam * ARAD );
+ writer->writeInt16( 73, a->isccw );
+ break;
+ }
+
+ case DRW::SPLINE:
+ // RLZ: spline boundary writeme
+// writer->writeInt16(72, 4);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ writer->writeInt16( 97, 0 );
+ }
+ }
+
+ writer->writeInt16( 75, ent->hstyle );
+ writer->writeInt16( 76, ent->hpattern );
+
+ if( !ent->solid )
+ {
+ writer->writeDouble( 52, ent->angle );
+ writer->writeDouble( 41, ent->scale );
+ writer->writeInt16( 77, ent->doubleflag );
+ writer->writeInt16( 78, ent->deflines );
+ }
+
+/* if (ent->deflines > 0){
+ * writer->writeInt16(78, ent->deflines);
+ * }*/
+ writer->writeInt32( 98, 0 );
+ }
+ else
+ {
+ // RLZ: TODO verify in acad12
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeLeader( DRW_Leader* ent )
+{
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "LEADER" );
+ writeEntity( ent );
+ writer->writeString( 100, "AcDbLeader" );
+ writer->writeUtf8String( 3, ent->style );
+ writer->writeInt16( 71, ent->arrow );
+ writer->writeInt16( 72, ent->leadertype );
+ writer->writeInt16( 73, ent->flag );
+ writer->writeInt16( 74, ent->hookline );
+ writer->writeInt16( 75, ent->hookflag );
+ writer->writeDouble( 40, ent->textheight );
+ writer->writeDouble( 41, ent->textwidth );
+ writer->writeDouble( 76, ent->vertnum );
+ writer->writeDouble( 76, ent->vertexlist.size() );
+
+ for( unsigned int i = 0; i<ent->vertexlist.size(); i++ )
+ {
+ DRW_Coord* vert = ent->vertexlist.at( i );
+ writer->writeDouble( 10, vert->x );
+ writer->writeDouble( 20, vert->y );
+ writer->writeDouble( 30, vert->z );
+ }
+ }
+ else
+ {
+ // RLZ: todo not supported by acad 12 saved as unnamed block
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeDimension( DRW_Dimension* ent )
+{
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "DIMENSION" );
+ writeEntity( ent );
+ writer->writeString( 100, "AcDbDimension" );
+
+ if( !ent->getName().empty() )
+ {
+ writer->writeString( 2, ent->getName() );
+ }
+
+ writer->writeDouble( 10, ent->getDefPoint().x );
+ writer->writeDouble( 20, ent->getDefPoint().y );
+ writer->writeDouble( 30, ent->getDefPoint().z );
+ writer->writeDouble( 11, ent->getTextPoint().x );
+ writer->writeDouble( 21, ent->getTextPoint().y );
+ writer->writeDouble( 31, ent->getTextPoint().z );
+
+ if( !(ent->type & 32) )
+ ent->type = ent->type + 32;
+
+ writer->writeInt16( 70, ent->type );
+
+ if( !( ent->getText().empty() ) )
+ writer->writeUtf8String( 1, ent->getText() );
+
+ writer->writeInt16( 71, ent->getAlign() );
+
+ if( ent->getTextLineStyle() != 1 )
+ writer->writeInt16( 72, ent->getTextLineStyle() );
+
+ if( ent->getTextLineFactor() != 1 )
+ writer->writeDouble( 41, ent->getTextLineFactor() );
+
+ writer->writeUtf8String( 3, ent->getStyle() );
+
+ if( ent->getDir() != 0 )
+ writer->writeDouble( 53, ent->getDir() );
+
+ writer->writeDouble( 210, ent->getExtrusion().x );
+ writer->writeDouble( 220, ent->getExtrusion().y );
+ writer->writeDouble( 230, ent->getExtrusion().z );
+
+ switch( ent->eType )
+ {
+ case DRW::DIMALIGNED:
+ case DRW::DIMLINEAR:
+ {
+ DRW_DimAligned* dd = (DRW_DimAligned*) ent;
+ writer->writeString( 100, "AcDbAlignedDimension" );
+ DRW_Coord crd = dd->getClonepoint();
+
+ if( crd.x != 0 || crd.y != 0 || crd.z != 0 )
+ {
+ writer->writeDouble( 12, crd.x );
+ writer->writeDouble( 22, crd.y );
+ writer->writeDouble( 32, crd.z );
+ }
+
+ writer->writeDouble( 13, dd->getDef1Point().x );
+ writer->writeDouble( 23, dd->getDef1Point().y );
+ writer->writeDouble( 33, dd->getDef1Point().z );
+ writer->writeDouble( 14, dd->getDef2Point().x );
+ writer->writeDouble( 24, dd->getDef2Point().y );
+ writer->writeDouble( 34, dd->getDef2Point().z );
+
+ if( ent->eType == DRW::DIMLINEAR )
+ {
+ DRW_DimLinear* dl = (DRW_DimLinear*) ent;
+
+ if( dl->getAngle() != 0 )
+ writer->writeDouble( 50, dl->getAngle() );
+
+ if( dl->getOblique() != 0 )
+ writer->writeDouble( 52, dl->getOblique() );
+
+ writer->writeString( 100, "AcDbRotatedDimension" );
+ }
+
+ break;
+ }
+
+ case DRW::DIMRADIAL:
+ {
+ DRW_DimRadial* dd = (DRW_DimRadial*) ent;
+ writer->writeString( 100, "AcDbRadialDimension" );
+ writer->writeDouble( 15, dd->getDiameterPoint().x );
+ writer->writeDouble( 25, dd->getDiameterPoint().y );
+ writer->writeDouble( 35, dd->getDiameterPoint().z );
+ writer->writeDouble( 40, dd->getLeaderLength() );
+ break;
+ }
+
+ case DRW::DIMDIAMETRIC:
+ {
+ DRW_DimDiametric* dd = (DRW_DimDiametric*) ent;
+ writer->writeString( 100, "AcDbDiametricDimension" );
+ writer->writeDouble( 15, dd->getDiameter1Point().x );
+ writer->writeDouble( 25, dd->getDiameter1Point().y );
+ writer->writeDouble( 35, dd->getDiameter1Point().z );
+ writer->writeDouble( 40, dd->getLeaderLength() );
+ break;
+ }
+
+ case DRW::DIMANGULAR:
+ {
+ DRW_DimAngular* dd = (DRW_DimAngular*) ent;
+ writer->writeString( 100, "AcDb2LineAngularDimension" );
+ writer->writeDouble( 13, dd->getFirstLine1().x );
+ writer->writeDouble( 23, dd->getFirstLine1().y );
+ writer->writeDouble( 33, dd->getFirstLine1().z );
+ writer->writeDouble( 14, dd->getFirstLine2().x );
+ writer->writeDouble( 24, dd->getFirstLine2().y );
+ writer->writeDouble( 34, dd->getFirstLine2().z );
+ writer->writeDouble( 15, dd->getSecondLine1().x );
+ writer->writeDouble( 25, dd->getSecondLine1().y );
+ writer->writeDouble( 35, dd->getSecondLine1().z );
+ writer->writeDouble( 16, dd->getDimPoint().x );
+ writer->writeDouble( 26, dd->getDimPoint().y );
+ writer->writeDouble( 36, dd->getDimPoint().z );
+ break;
+ }
+
+ case DRW::DIMANGULAR3P:
+ {
+ DRW_DimAngular3p* dd = (DRW_DimAngular3p*) ent;
+ writer->writeDouble( 13, dd->getFirstLine().x );
+ writer->writeDouble( 23, dd->getFirstLine().y );
+ writer->writeDouble( 33, dd->getFirstLine().z );
+ writer->writeDouble( 14, dd->getSecondLine().x );
+ writer->writeDouble( 24, dd->getSecondLine().y );
+ writer->writeDouble( 34, dd->getSecondLine().z );
+ writer->writeDouble( 15, dd->getVertexPoint().x );
+ writer->writeDouble( 25, dd->getVertexPoint().y );
+ writer->writeDouble( 35, dd->getVertexPoint().z );
+ break;
+ }
+
+ case DRW::DIMORDINATE:
+ {
+ DRW_DimOrdinate* dd = (DRW_DimOrdinate*) ent;
+ writer->writeString( 100, "AcDbOrdinateDimension" );
+ writer->writeDouble( 13, dd->getFirstLine().x );
+ writer->writeDouble( 23, dd->getFirstLine().y );
+ writer->writeDouble( 33, dd->getFirstLine().z );
+ writer->writeDouble( 14, dd->getSecondLine().x );
+ writer->writeDouble( 24, dd->getSecondLine().y );
+ writer->writeDouble( 34, dd->getSecondLine().z );
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // RLZ: todo not supported by acad 12 saved as unnamed block
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeInsert( DRW_Insert* ent )
+{
+ writer->writeString( 0, "INSERT" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbBlockReference" );
+ writer->writeUtf8String( 2, ent->name );
+ }
+ else
+ writer->writeUtf8Caps( 2, ent->name );
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 41, ent->xscale );
+ writer->writeDouble( 42, ent->yscale );
+ writer->writeDouble( 43, ent->zscale );
+ writer->writeDouble( 50, ent->angle );
+ writer->writeInt16( 70, ent->colcount );
+ writer->writeInt16( 71, ent->rowcount );
+ writer->writeDouble( 44, ent->colspace );
+ writer->writeDouble( 45, ent->rowspace );
+ return true;
+}
+
+
+bool dxfRW::writeText( DRW_Text* ent )
+{
+ writer->writeString( 0, "TEXT" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbText" );
+ }
+
+// writer->writeDouble(39, ent->thickness);
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 40, ent->height );
+ writer->writeUtf8String( 1, ent->text );
+ writer->writeDouble( 50, ent->angle );
+ writer->writeDouble( 41, ent->widthscale );
+ writer->writeDouble( 51, ent->oblique );
+
+ if( version > DRW::AC1009 )
+ writer->writeUtf8String( 7, ent->style );
+ else
+ writer->writeUtf8Caps( 7, ent->style );
+
+ writer->writeInt16( 71, ent->textgen );
+
+ if( ent->alignH != DRW_Text::HLeft )
+ {
+ writer->writeInt16( 72, ent->alignH );
+ }
+
+ if( ent->alignH != DRW_Text::HLeft || ent->alignV != DRW_Text::VBaseLine )
+ {
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ writer->writeDouble( 31, ent->secPoint.z );
+ }
+
+ writer->writeDouble( 210, ent->extPoint.x );
+ writer->writeDouble( 220, ent->extPoint.y );
+ writer->writeDouble( 230, ent->extPoint.z );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbText" );
+ }
+
+ if( ent->alignV != DRW_Text::VBaseLine )
+ {
+ writer->writeInt16( 73, ent->alignV );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeMText( DRW_MText* ent )
+{
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "MTEXT" );
+ writeEntity( ent );
+ writer->writeString( 100, "AcDbMText" );
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 40, ent->height );
+ writer->writeDouble( 41, ent->widthscale );
+ writer->writeInt16( 71, ent->textgen );
+ writer->writeInt16( 72, ent->alignH );
+ std::string text = writer->fromUtf8String( ent->text );
+
+ int i;
+
+ for( i = 0; (text.size() - i) > 250; )
+ {
+ writer->writeString( 3, text.substr( i, 250 ) );
+ i += 250;
+ }
+
+ writer->writeString( 1, text.substr( i ) );
+ writer->writeString( 7, ent->style );
+ writer->writeDouble( 210, ent->extPoint.x );
+ writer->writeDouble( 220, ent->extPoint.y );
+ writer->writeDouble( 230, ent->extPoint.z );
+ writer->writeDouble( 50, ent->angle );
+ writer->writeInt16( 73, ent->alignV );
+ writer->writeDouble( 44, ent->interlin );
+// RLZ ... 11, 21, 31 needed?
+ }
+ else
+ {
+ // RLZ: TODO convert mtext in text lines (not exist in acad 12)
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeViewport( DRW_Viewport* ent )
+{
+ writer->writeString( 0, "VIEWPORT" );
+ writeEntity( ent );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbViewport" );
+ }
+
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+
+ if( ent->basePoint.z != 0.0 )
+ writer->writeDouble( 30, ent->basePoint.z );
+
+ writer->writeDouble( 40, ent->pswidth );
+ writer->writeDouble( 41, ent->psheight );
+ writer->writeInt16( 68, ent->vpstatus );
+ writer->writeInt16( 69, ent->vpID );
+ writer->writeDouble( 12, ent->centerPX ); // RLZ: verify if exist in V12
+ writer->writeDouble( 22, ent->centerPY ); // RLZ: verify if exist in V12
+ return true;
+}
+
+
+DRW_ImageDef* dxfRW::writeImage( DRW_Image* ent, std::string name )
+{
+ if( version > DRW::AC1009 )
+ {
+ // search if exist imagedef with this mane (image inserted more than 1 time)
+ // RLZ: imagedef_reactor seem needed to read in acad
+ DRW_ImageDef* id = NULL;
+
+ for( unsigned int i = 0; i<imageDef.size(); i++ )
+ {
+ if( imageDef.at( i )->name == name )
+ {
+ id = imageDef.at( i );
+ continue;
+ }
+ }
+
+ if( id == NULL )
+ {
+ id = new DRW_ImageDef();
+ imageDef.push_back( id );
+ id->handle = toHexStr( ++entCount );
+ }
+
+ id->name = name;
+ std::string idReactor = toHexStr( ++entCount );
+
+ writer->writeString( 0, "IMAGE" );
+ writeEntity( ent );
+ writer->writeString( 100, "AcDbRasterImage" );
+ writer->writeDouble( 10, ent->basePoint.x );
+ writer->writeDouble( 20, ent->basePoint.y );
+ writer->writeDouble( 30, ent->basePoint.z );
+ writer->writeDouble( 11, ent->secPoint.x );
+ writer->writeDouble( 21, ent->secPoint.y );
+ writer->writeDouble( 31, ent->secPoint.z );
+ writer->writeDouble( 12, ent->vx );
+ writer->writeDouble( 22, ent->vy );
+ writer->writeDouble( 32, ent->vz );
+ writer->writeDouble( 13, ent->sizeu );
+ writer->writeDouble( 23, ent->sizev );
+ writer->writeString( 340, id->handle );
+ writer->writeInt16( 70, 1 );
+ writer->writeInt16( 280, ent->clip );
+ writer->writeInt16( 281, ent->brightness );
+ writer->writeInt16( 282, ent->contrast );
+ writer->writeInt16( 283, ent->fade );
+ writer->writeString( 360, idReactor );
+ id->reactors[idReactor] = toHexStr( ent->handle );
+ return id;
+ }
+
+ return NULL; // not exist in acad 12
+}
+
+
+bool dxfRW::writeBlockRecord( std::string name )
+{
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "BLOCK_RECORD" );
+ writer->writeString( 5, toHexStr( ++entCount ) );
+
+ blockMap[name] = entCount;
+ entCount = 2 + entCount; // reserve 2 for BLOCK & ENDBLOCK
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "1" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbBlockTableRecord" );
+ writer->writeUtf8String( 2, name );
+
+ if( version > DRW::AC1018 )
+ {
+ // writer->writeInt16(340, 22);
+ writer->writeInt16( 70, 0 );
+ writer->writeInt16( 280, 1 );
+ writer->writeInt16( 281, 0 );
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeBlock( DRW_Block* bk )
+{
+ if( writingBlock )
+ {
+ writer->writeString( 0, "ENDBLK" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, toHexStr( currHandle + 2 ) );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, toHexStr( currHandle ) );
+ }
+
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ writer->writeString( 8, "0" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbBlockEnd" );
+ }
+ }
+
+ writingBlock = true;
+ writer->writeString( 0, "BLOCK" );
+
+ if( version > DRW::AC1009 )
+ {
+ currHandle = ( *( blockMap.find( bk->name ) ) ).second;
+ writer->writeString( 5, toHexStr( currHandle + 1 ) );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, toHexStr( currHandle ) );
+ }
+
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ writer->writeString( 8, "0" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbBlockBegin" );
+ writer->writeUtf8String( 2, bk->name );
+ }
+ else
+ writer->writeUtf8Caps( 2, bk->name );
+
+ writer->writeInt16( 70, bk->flags );
+ writer->writeDouble( 10, bk->basePoint.x );
+ writer->writeDouble( 20, bk->basePoint.y );
+
+ if( bk->basePoint.z != 0.0 )
+ {
+ writer->writeDouble( 30, bk->basePoint.z );
+ }
+
+ if( version > DRW::AC1009 )
+ writer->writeUtf8String( 3, bk->name );
+ else
+ writer->writeUtf8Caps( 3, bk->name );
+
+ writer->writeString( 1, "" );
+
+ return true;
+}
+
+
+bool dxfRW::writeTables()
+{
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "VPORT" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "8" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 1 ); // end table def
+/*** VPORT ***/
+ dimstyleStd = false;
+ iface->writeVports();
+
+ if( !dimstyleStd )
+ {
+ DRW_Vport portact;
+ portact.name = "*ACTIVE";
+ writeVport( &portact );
+ }
+
+ writer->writeString( 0, "ENDTAB" );
+/*** LTYPE ***/
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "LTYPE" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "5" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 4 ); // end table def
+// Mandatory linetypes
+ writer->writeString( 0, "LTYPE" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "14" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "5" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbLinetypeTableRecord" );
+ writer->writeString( 2, "ByBlock" );
+ }
+ else
+ writer->writeString( 2, "BYBLOCK" );
+
+ writer->writeInt16( 70, 0 );
+ writer->writeString( 3, "" );
+ writer->writeInt16( 72, 65 );
+ writer->writeInt16( 73, 0 );
+ writer->writeDouble( 40, 0.0 );
+
+ writer->writeString( 0, "LTYPE" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "15" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "5" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbLinetypeTableRecord" );
+ writer->writeString( 2, "ByLayer" );
+ }
+ else
+ writer->writeString( 2, "BYLAYER" );
+
+ writer->writeInt16( 70, 0 );
+ writer->writeString( 3, "" );
+ writer->writeInt16( 72, 65 );
+ writer->writeInt16( 73, 0 );
+ writer->writeDouble( 40, 0.0 );
+
+ writer->writeString( 0, "LTYPE" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "16" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "5" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbLinetypeTableRecord" );
+ writer->writeString( 2, "Continuous" );
+ }
+ else
+ {
+ writer->writeString( 2, "CONTINUOUS" );
+ }
+
+ writer->writeInt16( 70, 0 );
+ writer->writeString( 3, "Solid line" );
+ writer->writeInt16( 72, 65 );
+ writer->writeInt16( 73, 0 );
+ writer->writeDouble( 40, 0.0 );
+// Aplication linetypes
+ iface->writeLTypes();
+ writer->writeString( 0, "ENDTAB" );
+/*** LAYER ***/
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "LAYER" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "2" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 1 ); // end table def
+ wlayer0 = false;
+ iface->writeLayers();
+
+ if( !wlayer0 )
+ {
+ DRW_Layer lay0;
+ lay0.name = "0";
+ writeLayer( &lay0 );
+ }
+
+ writer->writeString( 0, "ENDTAB" );
+/*** STYLE ***/
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "STYLE" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "3" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 3 ); // end table def
+ dimstyleStd = false;
+ iface->writeTextstyles();
+
+ if( !dimstyleStd )
+ {
+ DRW_Textstyle tsty;
+ tsty.name = "Standard";
+ writeTextstyle( &tsty );
+ }
+
+ writer->writeString( 0, "ENDTAB" );
+
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "VIEW" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "6" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 0 ); // end table def
+ writer->writeString( 0, "ENDTAB" );
+
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "UCS" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "7" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 0 ); // end table def
+ writer->writeString( 0, "ENDTAB" );
+
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "APPID" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "9" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 1 ); // end table def
+ writer->writeString( 0, "APPID" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "12" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "9" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbRegAppTableRecord" );
+ }
+
+ writer->writeString( 2, "ACAD" );
+ writer->writeInt16( 70, 0 );
+ iface->writeAppId();
+ writer->writeString( 0, "ENDTAB" );
+
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "DIMSTYLE" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "A" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ }
+
+ writer->writeInt16( 70, 1 ); // end table def
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 100, "AcDbDimStyleTable" );
+ writer->writeInt16( 71, 1 ); // end table def
+ }
+
+ dimstyleStd = false;
+ iface->writeDimstyles();
+
+ if( !dimstyleStd )
+ {
+ DRW_Dimstyle dsty;
+ dsty.name = "Standard";
+ writeDimstyle( &dsty );
+ }
+
+ writer->writeString( 0, "ENDTAB" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "TABLE" );
+ writer->writeString( 2, "BLOCK_RECORD" );
+ writer->writeString( 5, "1" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTable" );
+ writer->writeInt16( 70, 2 ); // end table def
+ writer->writeString( 0, "BLOCK_RECORD" );
+ writer->writeString( 5, "1F" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "1" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbBlockTableRecord" );
+ writer->writeString( 2, "*Model_Space" );
+
+ if( version > DRW::AC1018 )
+ {
+ // writer->writeInt16(340, 22);
+ writer->writeInt16( 70, 0 );
+ writer->writeInt16( 280, 1 );
+ writer->writeInt16( 281, 0 );
+ }
+
+ writer->writeString( 0, "BLOCK_RECORD" );
+ writer->writeString( 5, "1E" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "1" );
+ }
+
+ writer->writeString( 100, "AcDbSymbolTableRecord" );
+ writer->writeString( 100, "AcDbBlockTableRecord" );
+ writer->writeString( 2, "*Paper_Space" );
+
+ if( version > DRW::AC1018 )
+ {
+ // writer->writeInt16(340, 22);
+ writer->writeInt16( 70, 0 );
+ writer->writeInt16( 280, 1 );
+ writer->writeInt16( 281, 0 );
+ }
+ }
+
+ /* allways call writeBlockRecords to iface for prepare unnamed blocks */
+ iface->writeBlockRecords();
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 0, "ENDTAB" );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeBlocks()
+{
+ writer->writeString( 0, "BLOCK" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "20" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "1F" );
+ }
+
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ writer->writeString( 8, "0" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbBlockBegin" );
+ writer->writeString( 2, "*Model_Space" );
+ }
+ else
+ writer->writeString( 2, "$MODEL_SPACE" );
+
+ writer->writeInt16( 70, 0 );
+ writer->writeDouble( 10, 0.0 );
+ writer->writeDouble( 20, 0.0 );
+ writer->writeDouble( 30, 0.0 );
+
+ if( version > DRW::AC1009 )
+ writer->writeString( 3, "*Model_Space" );
+ else
+ writer->writeString( 3, "$MODEL_SPACE" );
+
+ writer->writeString( 1, "" );
+ writer->writeString( 0, "ENDBLK" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "21" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "1F" );
+ }
+
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ writer->writeString( 8, "0" );
+
+ if( version > DRW::AC1009 )
+ writer->writeString( 100, "AcDbBlockEnd" );
+
+ writer->writeString( 0, "BLOCK" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "1C" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "1B" );
+ }
+
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ writer->writeString( 8, "0" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 100, "AcDbBlockBegin" );
+ writer->writeString( 2, "*Paper_Space" );
+ }
+ else
+ writer->writeString( 2, "$PAPER_SPACE" );
+
+ writer->writeInt16( 70, 0 );
+ writer->writeDouble( 10, 0.0 );
+ writer->writeDouble( 20, 0.0 );
+ writer->writeDouble( 30, 0.0 );
+
+ if( version > DRW::AC1009 )
+ writer->writeString( 3, "*Paper_Space" );
+ else
+ writer->writeString( 3, "$PAPER_SPACE" );
+
+ writer->writeString( 1, "" );
+ writer->writeString( 0, "ENDBLK" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, "1D" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "1F" );
+ }
+
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ writer->writeString( 8, "0" );
+
+ if( version > DRW::AC1009 )
+ writer->writeString( 100, "AcDbBlockEnd" );
+
+ writingBlock = false;
+ iface->writeBlocks();
+
+ if( writingBlock )
+ {
+ writingBlock = false;
+ writer->writeString( 0, "ENDBLK" );
+
+ if( version > DRW::AC1009 )
+ {
+ writer->writeString( 5, toHexStr( currHandle + 2 ) );
+
+// writer->writeString(5, "1D");
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, toHexStr( currHandle ) );
+ }
+
+ writer->writeString( 100, "AcDbEntity" );
+ }
+
+ writer->writeString( 8, "0" );
+
+ if( version > DRW::AC1009 )
+ writer->writeString( 100, "AcDbBlockEnd" );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeObjects()
+{
+ writer->writeString( 0, "DICTIONARY" );
+ std::string imgDictH;
+ writer->writeString( 5, "C" );
+
+ if( version > DRW::AC1014 )
+ {
+ writer->writeString( 330, "0" );
+ }
+
+ writer->writeString( 100, "AcDbDictionary" );
+ writer->writeInt16( 281, 1 );
+ writer->writeString( 3, "ACAD_GROUP" );
+ writer->writeString( 350, "D" );
+
+ if( imageDef.size() != 0 )
+ {
+ writer->writeString( 3, "ACAD_IMAGE_DICT" );
+ imgDictH = toHexStr( ++entCount );
+ writer->writeString( 350, imgDictH );
+ }
+
+ writer->writeString( 0, "DICTIONARY" );
+ writer->writeString( 5, "D" );
+ writer->writeString( 330, "C" );
+ writer->writeString( 100, "AcDbDictionary" );
+ writer->writeInt16( 281, 1 );
+
+// write IMAGEDEF_REACTOR
+ for( unsigned int i = 0; i<imageDef.size(); i++ )
+ {
+ DRW_ImageDef* id = imageDef.at( i );
+ std::map<std::string, std::string>::iterator it;
+
+ for( it = id->reactors.begin(); it != id->reactors.end(); ++it )
+ {
+ writer->writeString( 0, "IMAGEDEF_REACTOR" );
+ writer->writeString( 5, (*it).first );
+ writer->writeString( 330, (*it).second );
+ writer->writeString( 100, "AcDbRasterImageDefReactor" );
+ writer->writeInt16( 90, 2 ); // version 2=R14 to v2010
+ writer->writeString( 330, (*it).second );
+ }
+ }
+
+ if( imageDef.size() != 0 )
+ {
+ writer->writeString( 0, "DICTIONARY" );
+ writer->writeString( 5, imgDictH );
+ writer->writeString( 330, "C" );
+ writer->writeString( 100, "AcDbDictionary" );
+ writer->writeInt16( 281, 1 );
+
+ for( unsigned int i = 0; i<imageDef.size(); i++ )
+ {
+ size_t f1, f2;
+ f1 = imageDef.at( i )->name.find_last_of( "/\\" );
+ f2 = imageDef.at( i )->name.find_last_of( '.' );
+ ++f1;
+ writer->writeString( 3, imageDef.at( i )->name.substr( f1, f2 - f1 ) );
+ writer->writeString( 350, imageDef.at( i )->handle );
+ }
+ }
+
+ for( unsigned int i = 0; i<imageDef.size(); i++ )
+ {
+ DRW_ImageDef* id = imageDef.at( i );
+ writer->writeString( 0, "IMAGEDEF" );
+ writer->writeString( 5, id->handle );
+
+ if( version > DRW::AC1014 )
+ {
+// writer->writeString(330, "0"); handle to DICTIONARY
+ }
+
+ writer->writeString( 102, "{ACAD_REACTORS" );
+ std::map<std::string, std::string>::iterator it;
+
+ for( it = id->reactors.begin(); it != id->reactors.end(); ++it )
+ {
+ writer->writeString( 330, (*it).first );
+ }
+
+ writer->writeString( 102, "}" );
+ writer->writeString( 100, "AcDbRasterImageDef" );
+ writer->writeInt16( 90, 0 ); // version 0=R14 to v2010
+ writer->writeUtf8String( 1, id->name );
+ writer->writeDouble( 10, id->u );
+ writer->writeDouble( 20, id->v );
+ writer->writeDouble( 11, id->up );
+ writer->writeDouble( 21, id->vp );
+ writer->writeInt16( 280, id->loaded );
+ writer->writeInt16( 281, id->resolution );
+ }
+
+ // no more needed imageDef, delete it
+ while( !imageDef.empty() )
+ {
+ imageDef.pop_back();
+ }
+
+ return true;
+}
+
+
+bool dxfRW::writeExtData( const std::vector<DRW_Variant*>& ed )
+{
+ for( std::vector<DRW_Variant*>::const_iterator it = ed.begin(); it!=ed.end(); ++it )
+ {
+ switch( (*it)->code )
+ {
+ case 1000:
+ case 1001:
+ case 1002:
+ case 1003:
+ case 1004:
+ case 1005:
+ {
+ int cc = (*it)->code;
+
+ if( (*it)->type == DRW_Variant::STRING )
+ writer->writeUtf8String( cc, *(*it)->content.s );
+
+// writer->writeUtf8String((*it)->code, (*it)->content.s);
+ break;
+ }
+
+ case 1010:
+ case 1011:
+ case 1012:
+ case 1013:
+
+ if( (*it)->type == DRW_Variant::COORD )
+ {
+ writer->writeDouble( (*it)->code, (*it)->content.v->x );
+ writer->writeDouble( (*it)->code + 10, (*it)->content.v->y );
+ writer->writeDouble( (*it)->code + 20, (*it)->content.v->z );
+ }
+
+ break;
+
+ case 1040:
+ case 1041:
+ case 1042:
+
+ if( (*it)->type == DRW_Variant::DOUBLE )
+ writer->writeDouble( (*it)->code, (*it)->content.d );
+
+ break;
+
+ case 1070:
+
+ if( (*it)->type == DRW_Variant::INTEGER )
+ writer->writeInt16( (*it)->code, (*it)->content.i );
+
+ break;
+
+ case 1071:
+
+ if( (*it)->type == DRW_Variant::INTEGER )
+ writer->writeInt32( (*it)->code, (*it)->content.i );
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+/********* Reader Process *********/
+
+bool dxfRW::processDxf()
+{
+ DBG( "dxfRW::processDxf() start processing dxf\n" );
+ int code;
+ bool more = true;
+ std::string sectionstr;
+
+// section = secUnknown;
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( " processDxf\n" );
+
+ if( code == 999 )
+ {
+ header.addComment( reader->getString() );
+ }
+ else if( code == 0 )
+ {
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( " processDxf\n" );
+
+ if( sectionstr == "EOF" )
+ {
+ return true; // found EOF terminate
+ }
+
+ if( sectionstr == "SECTION" )
+ {
+ more = reader->readRec( &code, !binary );
+ DBG( code ); DBG( " processDxf\n" );
+
+ if( !more )
+ return false; // wrong dxf file
+
+ if( code == 2 )
+ {
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( " processDxf\n" );
+
+ // found section, process it
+ if( sectionstr == "HEADER" )
+ {
+ processHeader();
+ }
+ else if( sectionstr == "CLASSES" )
+ {
+// processClasses();
+ }
+ else if( sectionstr == "TABLES" )
+ {
+ processTables();
+ }
+ else if( sectionstr == "BLOCKS" )
+ {
+ processBlocks();
+ }
+ else if( sectionstr == "ENTITIES" )
+ {
+ processEntities( false );
+ }
+ else if( sectionstr == "OBJECTS" )
+ {
+ processObjects();
+ }
+ }
+ }
+ }
+
+/* if (!more)
+ * return true;*/
+ }
+
+ return true;
+}
+
+
+/********* Header Section *********/
+
+bool dxfRW::processHeader()
+{
+ DBG( "dxfRW::processHeader\n" );
+ int code;
+ std::string sectionstr;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( " processHeader\n" );
+
+ if( code == 0 )
+ {
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( " processHeader\n\n" );
+
+ if( sectionstr == "ENDSEC" )
+ {
+ iface->addHeader( &header );
+ return true; // found ENDSEC terminate
+ }
+ }
+ else
+ header.parseCode( code, reader );
+ }
+
+ return true;
+}
+
+
+/********* Tables Section *********/
+
+bool dxfRW::processTables()
+{
+ DBG( "dxfRW::processTables\n" );
+ int code;
+ std::string sectionstr;
+ bool more = true;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( " processHeader\n\n" );
+
+ if( sectionstr == "TABLE" )
+ {
+ more = reader->readRec( &code, !binary );
+ DBG( code ); DBG( "\n" );
+
+ if( !more )
+ return false; // wrong dxf file
+
+ if( code == 2 )
+ {
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( " processHeader\n\n" );
+
+ // found section, process it
+ if( sectionstr == "LTYPE" )
+ {
+ processLType();
+ }
+ else if( sectionstr == "LAYER" )
+ {
+ processLayer();
+ }
+ else if( sectionstr == "STYLE" )
+ {
+ processTextStyle();
+ }
+ else if( sectionstr == "VPORT" )
+ {
+ processVports();
+ }
+ else if( sectionstr == "VIEW" )
+ {
+// processView();
+ }
+ else if( sectionstr == "UCS" )
+ {
+// processUCS();
+ }
+ else if( sectionstr == "APPID" )
+ {
+ processAppId();
+ }
+ else if( sectionstr == "DIMSTYLE" )
+ {
+ processDimStyle();
+ }
+ else if( sectionstr == "BLOCK_RECORD" )
+ {
+// processBlockRecord();
+ }
+ }
+ }
+ else if( sectionstr == "ENDSEC" )
+ {
+ return true; // found ENDSEC terminate
+ }
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processLType()
+{
+ DBG( "dxfRW::processLType\n" );
+ int code;
+ std::string sectionstr;
+ bool reading = false;
+ DRW_LType ltype;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ if( reading )
+ {
+ ltype.update();
+ iface->addLType( ltype );
+ }
+
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( "\n" );
+
+ if( sectionstr == "LTYPE" )
+ {
+ reading = true;
+ ltype.reset();
+ }
+ else if( sectionstr == "ENDTAB" )
+ {
+ return true; // found ENDTAB terminate
+ }
+ }
+ else if( reading )
+ ltype.parseCode( code, reader );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processLayer()
+{
+ DBG( "dxfRW::processLayer\n" );
+ int code;
+ std::string sectionstr;
+ bool reading = false;
+ DRW_Layer layer;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ if( reading )
+ iface->addLayer( layer );
+
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( "\n" );
+
+ if( sectionstr == "LAYER" )
+ {
+ reading = true;
+ layer.reset();
+ }
+ else if( sectionstr == "ENDTAB" )
+ {
+ return true; // found ENDTAB terminate
+ }
+ }
+ else if( reading )
+ layer.parseCode( code, reader );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processDimStyle()
+{
+ DBG( "dxfRW::processDimStyle" );
+ int code;
+ std::string sectionstr;
+ bool reading = false;
+ DRW_Dimstyle dimSty;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ if( reading )
+ iface->addDimStyle( dimSty );
+
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( "\n" );
+
+ if( sectionstr == "DIMSTYLE" )
+ {
+ reading = true;
+ dimSty.reset();
+ }
+ else if( sectionstr == "ENDTAB" )
+ {
+ return true; // found ENDTAB terminate
+ }
+ }
+ else if( reading )
+ dimSty.parseCode( code, reader );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processTextStyle()
+{
+ DBG( "dxfRW::processTextStyle" );
+ int code;
+ std::string sectionstr;
+ bool reading = false;
+ DRW_Textstyle TxtSty;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ if( reading )
+ iface->addTextStyle( TxtSty );
+
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( "\n" );
+
+ if( sectionstr == "STYLE" )
+ {
+ reading = true;
+ TxtSty.reset();
+ }
+ else if( sectionstr == "ENDTAB" )
+ {
+ return true; // found ENDTAB terminate
+ }
+ }
+ else if( reading )
+ TxtSty.parseCode( code, reader );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processVports()
+{
+ DBG( "dxfRW::processVports" );
+ int code;
+ std::string sectionstr;
+ bool reading = false;
+ DRW_Vport vp;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ if( reading )
+ iface->addVport( vp );
+
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( "\n" );
+
+ if( sectionstr == "VPORT" )
+ {
+ reading = true;
+ vp.reset();
+ }
+ else if( sectionstr == "ENDTAB" )
+ {
+ return true; // found ENDTAB terminate
+ }
+ }
+ else if( reading )
+ vp.parseCode( code, reader );
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processAppId()
+{
+ DBG( "dxfRW::processAppId" );
+ int code;
+ std::string sectionstr;
+ bool reading = false;
+ DRW_AppId vp;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ if( reading )
+ iface->addAppId( vp );
+
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( "\n" );
+
+ if( sectionstr == "APPID" )
+ {
+ reading = true;
+ vp.reset();
+ }
+ else if( sectionstr == "ENDTAB" )
+ {
+ return true; // found ENDTAB terminate
+ }
+ }
+ else if( reading )
+ vp.parseCode( code, reader );
+ }
+
+ return true;
+}
+
+
+/********* Block Section *********/
+
+bool dxfRW::processBlocks()
+{
+ DBG( "dxfRW::processBlocks\n" );
+ int code;
+ std::string sectionstr;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ if( code == 0 )
+ {
+ sectionstr = reader->getString();
+ DBG( sectionstr ); DBG( "\n" );
+
+ if( sectionstr == "BLOCK" )
+ {
+ processBlock();
+ }
+ else if( sectionstr == "ENDSEC" )
+ {
+ return true; // found ENDSEC terminate
+ }
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processBlock()
+{
+ DBG( "dxfRW::processBlock" );
+ int code;
+ DRW_Block block;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addBlock( block );
+
+ if( nextentity == "ENDBLK" )
+ {
+ iface->endBlock();
+ return true; // found ENDBLK, terminate
+ }
+ else
+ {
+ processEntities( true );
+ iface->endBlock();
+ return true; // found ENDBLK, terminate
+ }
+ }
+
+ default:
+ block.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+/********* Entities Section *********/
+
+bool dxfRW::processEntities( bool isblock )
+{
+ DBG( "dxfRW::processEntities\n" );
+ int code;
+
+ if( !reader->readRec( &code, !binary ) )
+ {
+ return false;
+ }
+
+ bool next = true;
+
+ if( code == 0 )
+ {
+ nextentity = reader->getString();
+ }
+ else if( !isblock )
+ {
+ return false; // first record in entities is 0
+ }
+
+ do {
+ if( nextentity == "ENDSEC" || nextentity == "ENDBLK" )
+ {
+ return true; // found ENDSEC or ENDBLK terminate
+ }
+ else if( nextentity == "POINT" )
+ {
+ processPoint();
+ }
+ else if( nextentity == "LINE" )
+ {
+ processLine();
+ }
+ else if( nextentity == "CIRCLE" )
+ {
+ processCircle();
+ }
+ else if( nextentity == "ARC" )
+ {
+ processArc();
+ }
+ else if( nextentity == "ELLIPSE" )
+ {
+ processEllipse();
+ }
+ else if( nextentity == "TRACE" )
+ {
+ processTrace();
+ }
+ else if( nextentity == "SOLID" )
+ {
+ processSolid();
+ }
+ else if( nextentity == "INSERT" )
+ {
+ processInsert();
+ }
+ else if( nextentity == "LWPOLYLINE" )
+ {
+ processLWPolyline();
+ }
+ else if( nextentity == "POLYLINE" )
+ {
+ processPolyline();
+ }
+ else if( nextentity == "TEXT" )
+ {
+ processText();
+ }
+ else if( nextentity == "MTEXT" )
+ {
+ processMText();
+ }
+ else if( nextentity == "HATCH" )
+ {
+ processHatch();
+ }
+ else if( nextentity == "SPLINE" )
+ {
+ processSpline();
+ }
+ else if( nextentity == "3DFACE" )
+ {
+ process3dface();
+ }
+ else if( nextentity == "VIEWPORT" )
+ {
+ processViewport();
+ }
+ else if( nextentity == "IMAGE" )
+ {
+ processImage();
+ }
+ else if( nextentity == "DIMENSION" )
+ {
+ processDimension();
+ }
+ else if( nextentity == "LEADER" )
+ {
+ processLeader();
+ }
+ else if( nextentity == "RAY" )
+ {
+ processRay();
+ }
+ else if( nextentity == "XLINE" )
+ {
+ processXline();
+ }
+ else
+ {
+ if( reader->readRec( &code, !binary ) )
+ {
+ if( code == 0 )
+ nextentity = reader->getString();
+ }
+ else
+ return false; // end of file without ENDSEC
+ }
+ } while( next );
+
+ return true;
+}
+
+
+bool dxfRW::processEllipse()
+{
+ DBG( "dxfRW::processEllipse" );
+ int code;
+ DRW_Ellipse ellipse;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( applyExt )
+ ellipse.applyExtrusion();
+
+ iface->addEllipse( ellipse );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ ellipse.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processTrace()
+{
+ DBG( "dxfRW::processTrace" );
+ int code;
+ DRW_Trace trace;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( applyExt )
+ trace.applyExtrusion();
+
+ iface->addTrace( trace );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ trace.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processSolid()
+{
+ DBG( "dxfRW::processSolid" );
+ int code;
+ DRW_Solid solid;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( applyExt )
+ solid.applyExtrusion();
+
+ iface->addSolid( solid );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ solid.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::process3dface()
+{
+ DBG( "dxfRW::process3dface" );
+ int code;
+ DRW_3Dface face;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->add3dFace( face );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ face.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processViewport()
+{
+ DBG( "dxfRW::processViewport" );
+ int code;
+ DRW_Viewport vp;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addViewport( vp );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ vp.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processPoint()
+{
+ DBG( "dxfRW::processPoint\n" );
+ int code;
+ DRW_Point point;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addPoint( point );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ point.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processLine()
+{
+ DBG( "dxfRW::processLine\n" );
+ int code;
+ DRW_Line line;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addLine( line );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ line.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processRay()
+{
+ DBG( "dxfRW::processRay\n" );
+ int code;
+ DRW_Ray line;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addRay( line );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ line.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processXline()
+{
+ DBG( "dxfRW::processXline\n" );
+ int code;
+ DRW_Xline line;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addXline( line );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ line.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processCircle()
+{
+ DBG( "dxfRW::processPoint\n" );
+ int code;
+ DRW_Circle circle;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( applyExt )
+ circle.applyExtrusion();
+
+ iface->addCircle( circle );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ circle.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processArc()
+{
+ DBG( "dxfRW::processPoint\n" );
+ int code;
+ DRW_Arc arc;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( applyExt )
+ arc.applyExtrusion();
+
+ iface->addArc( arc );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ arc.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processInsert()
+{
+ DBG( "dxfRW::processInsert" );
+ int code;
+ DRW_Insert insert;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addInsert( insert );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ insert.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processLWPolyline()
+{
+ DBG( "dxfRW::processLWPolyline" );
+ int code;
+ DRW_LWPolyline pl;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( applyExt )
+ pl.applyExtrusion();
+
+ iface->addLWPolyline( pl );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ pl.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processPolyline()
+{
+ DBG( "dxfRW::processPolyline" );
+ int code;
+ DRW_Polyline pl;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( nextentity != "VERTEX" )
+ {
+ iface->addPolyline( pl );
+ return true; // found new entity or ENDSEC, terminate
+ }
+ else
+ {
+ processVertex( &pl );
+ }
+ }
+ // Fall through
+ default:
+ pl.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processVertex( DRW_Polyline* pl )
+{
+ DBG( "dxfRW::processVertex" );
+ int code;
+ DRW_Vertex* v = new DRW_Vertex();
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ pl->appendVertex( v );
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+
+ if( nextentity == "SEQEND" )
+ {
+ return true; // found SEQEND no more vertex, terminate
+ }
+ else if( nextentity == "VERTEX" )
+ {
+ v = new DRW_Vertex(); // another vertex
+ }
+ }
+ // Fall through
+ default:
+ v->parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processText()
+{
+ DBG( "dxfRW::processText" );
+ int code;
+ DRW_Text txt;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addText( txt );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ txt.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processMText()
+{
+ DBG( "dxfRW::processMText" );
+ int code;
+ DRW_MText txt;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ txt.updateAngle();
+ iface->addMText( txt );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ txt.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processHatch()
+{
+ DBG( "dxfRW::processHatch" );
+ int code;
+ DRW_Hatch hatch;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addHatch( &hatch );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ hatch.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processSpline()
+{
+ DBG( "dxfRW::processSpline" );
+ int code;
+ DRW_Spline sp;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addSpline( &sp );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ sp.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processImage()
+{
+ DBG( "dxfRW::processImage" );
+ int code;
+ DRW_Image img;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addImage( &img );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ img.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processDimension()
+{
+ DBG( "dxfRW::processDimension" );
+ int code;
+ DRW_Dimension dim;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ int type = dim.type & 0x0F;
+
+ switch( type )
+ {
+ case 0:
+ {
+ DRW_DimLinear d( dim );
+ iface->addDimLinear( &d );
+ break;
+ }
+
+ case 1:
+ {
+ DRW_DimAligned d( dim );
+ iface->addDimAlign( &d );
+ break;
+ }
+
+ case 2:
+ {
+ DRW_DimAngular d( dim );
+ iface->addDimAngular( &d );
+ break;
+ }
+
+ case 3:
+ {
+ DRW_DimDiametric d( dim );
+ iface->addDimDiametric( &d );
+ break;
+ }
+
+ case 4:
+ {
+ DRW_DimRadial d( dim );
+ iface->addDimRadial( &d );
+ break;
+ }
+
+ case 5:
+ {
+ DRW_DimAngular3p d( dim );
+ iface->addDimAngular3P( &d );
+ break;
+ }
+
+ case 6:
+ {
+ DRW_DimOrdinate d( dim );
+ iface->addDimOrdinate( &d );
+ break;
+ }
+ }
+
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ dim.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool dxfRW::processLeader()
+{
+ DBG( "dxfRW::processLeader" );
+ int code;
+ DRW_Leader leader;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->addLeader( &leader );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ leader.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+/********* Objects Section *********/
+
+bool dxfRW::processObjects()
+{
+ DBG( "dxfRW::processObjects\n" );
+ int code;
+
+ if( !reader->readRec( &code, !binary ) )
+ {
+ return false;
+ }
+
+ bool next = true;
+
+ if( code == 0 )
+ {
+ nextentity = reader->getString();
+ }
+ else
+ {
+ return false; // first record in objects is 0
+ }
+
+ do {
+ if( nextentity == "ENDSEC" )
+ {
+ return true; // found ENDSEC terminate
+ }
+ else if( nextentity == "IMAGEDEF" )
+ {
+ processImageDef();
+ }
+ else
+ {
+ if( reader->readRec( &code, !binary ) )
+ {
+ if( code == 0 )
+ nextentity = reader->getString();
+ }
+ else
+ return false; // end of file without ENDSEC
+ }
+ } while( next );
+
+ return true;
+}
+
+
+bool dxfRW::processImageDef()
+{
+ DBG( "dxfRW::processImageDef" );
+ int code;
+ DRW_ImageDef img;
+
+ while( reader->readRec( &code, !binary ) )
+ {
+ DBG( code ); DBG( "\n" );
+
+ switch( code )
+ {
+ case 0:
+ {
+ nextentity = reader->getString();
+ DBG( nextentity ); DBG( "\n" );
+ iface->linkImage( &img );
+ return true; // found new entity or ENDSEC, terminate
+ }
+
+ default:
+ img.parseCode( code, reader );
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+/** utility function
+ * convert a int to string in hex
+ **/
+std::string dxfRW::toHexStr( int n )
+{
+#if defined(__APPLE__)
+ char buffer[9] = { '\0' };
+ snprintf( buffer, sizeof(buffer), "%X", n );
+ return std::string( buffer );
+#else
+ std::ostringstream Convert;
+ Convert << std::uppercase << std::hex << n;
+ return Convert.str();
+#endif
+}