You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							701 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							701 lines
						
					
					
						
							13 KiB
						
					
					
				| /**************************************************************************** | |
| ** Copyright (C) 2001-2013 RibbonSoft, GmbH. All rights reserved. | |
| ** Copyright (C) 2001 Robert J. Campbell Jr. | |
| ** | |
| ** This file is part of the dxflib project. | |
| ** | |
| ** This file is free software; you can redistribute it and/or modify | |
| ** it 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. | |
| ** | |
| ** Licensees holding valid dxflib Professional Edition licenses may use | |
| ** this file in accordance with the dxflib Commercial License | |
| ** Agreement provided with the Software. | |
| ** | |
| ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | |
| ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
| ** | |
| ** See http://www.ribbonsoft.com for further details. | |
| ** | |
| ** Contact info@ribbonsoft.com if any conditions of this licensing are | |
| ** not clear to you. | |
| ** | |
| **********************************************************************/ | |
| 
 | |
| #ifndef DL_WRITER_H | |
| #define DL_WRITER_H | |
|  | |
| #include "dl_global.h" | |
|  | |
| #ifndef _WIN32 | |
| #include <strings.h> | |
| #endif | |
|  | |
| #include <cstring> | |
| #include <iostream> | |
| #include <algorithm> | |
|  | |
| #include "dl_attributes.h" | |
| #include "dl_codes.h" | |
|  | |
| 
 | |
| /** | |
|  * Defines interface for writing low level DXF constructs to | |
|  * a file. Implementation is defined in derived classes that write | |
|  * to binary or ASCII files. | |
|  * | |
|  * Implements functions that write higher level constructs in terms of | |
|  * the low level ones. | |
|  * | |
|  * @todo Add error checking for string/entry length. | |
|  */ | |
| class DXFLIB_EXPORT DL_Writer | |
| { | |
| public: | |
|     /** | |
|      * @param version DXF version. Defaults to DL_VERSION_2002. | |
|      */ | |
|     DL_Writer( DL_Codes::version aversion ) : m_handle( 0x30 ) | |
|     { | |
|         version = aversion; | |
|         modelSpaceHandle    = 0; | |
|         paperSpaceHandle    = 0; | |
|         paperSpace0Handle   = 0; | |
|     } | |
| 
 | |
|     virtual ~DL_Writer() {} | |
|     ; | |
| 
 | |
|     /** Generic section for section 'name'. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  SECTION | |
|      *   2 | |
|      *  name | |
|      * </pre> | |
|      */ | |
|     void section( const char* name ) const | |
|     { | |
|         dxfString( 0, "SECTION" ); | |
|         dxfString( 2, name ); | |
|     } | |
| 
 | |
|     /** | |
|      * Section HEADER | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  SECTION | |
|      *   2 | |
|      *  HEADER | |
|      * </pre> | |
|      */ | |
|     void sectionHeader() const | |
|     { | |
|         section( "HEADER" ); | |
|     } | |
| 
 | |
|     /** | |
|      * Section TABLES | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  SECTION | |
|      *   2 | |
|      *  TABLES | |
|      * </pre> | |
|      */ | |
|     void sectionTables() const | |
|     { | |
|         section( "TABLES" ); | |
|     } | |
| 
 | |
|     /** | |
|      * Section BLOCKS | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  SECTION | |
|      *   2 | |
|      *  BLOCKS | |
|      * </pre> | |
|      */ | |
|     void sectionBlocks() const | |
|     { | |
|         section( "BLOCKS" ); | |
|     } | |
| 
 | |
|     /** | |
|      * Section ENTITIES | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  SECTION | |
|      *   2 | |
|      *  ENTITIES | |
|      * </pre> | |
|      */ | |
|     void sectionEntities() const | |
|     { | |
|         section( "ENTITIES" ); | |
|     } | |
| 
 | |
|     /** | |
|      * Section CLASSES | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  SECTION | |
|      *   2 | |
|      *  CLASSES | |
|      * </pre> | |
|      */ | |
|     void sectionClasses() const | |
|     { | |
|         section( "CLASSES" ); | |
|     } | |
| 
 | |
|     /** | |
|      * Section OBJECTS | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  SECTION | |
|      *   2 | |
|      *  OBJECTS | |
|      * </pre> | |
|      */ | |
|     void sectionObjects() const | |
|     { | |
|         section( "OBJECTS" ); | |
|     } | |
| 
 | |
|     /** | |
|      * End of a section. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  ENDSEC | |
|      * </pre> | |
|      */ | |
|     void sectionEnd() const | |
|     { | |
|         dxfString( 0, "ENDSEC" ); | |
|     } | |
| 
 | |
|     /** | |
|      * Generic table for table 'name' with 'num' entries: | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  TABLE | |
|      *   2 | |
|      *  name | |
|      *  70 | |
|      *   num | |
|      * </pre> | |
|      */ | |
|     void table( const char* name, int num, int h = 0 ) const | |
|     { | |
|         dxfString( 0, "TABLE" ); | |
|         dxfString( 2, name ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             if( h==0 ) | |
|             { | |
|                 handle(); | |
|             } | |
|             else | |
|             { | |
|                 dxfHex( 5, h ); | |
|             } | |
| 
 | |
|             dxfString( 100, "AcDbSymbolTable" ); | |
|         } | |
| 
 | |
|         dxfInt( 70, num ); | |
|     } | |
| 
 | |
|     /** Table for layers. | |
|      * | |
|      * @param num Number of layers in total. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  TABLE | |
|      *   2 | |
|      *  LAYER | |
|      *   70 | |
|      *      num | |
|      * </pre> | |
|      */ | |
|     void tableLayers( int num ) const | |
|     { | |
|         table( "LAYER", num, 2 ); | |
|     } | |
| 
 | |
|     /** Table for line types. | |
|      * | |
|      * @param num Number of line types in total. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  TABLE | |
|      *   2 | |
|      *  LTYPE | |
|      *   70 | |
|      *      num | |
|      * </pre> | |
|      */ | |
|     void tableLinetypes( int num ) const | |
|     { | |
|         // linetypeHandle = 5; | |
|         table( "LTYPE", num, 5 ); | |
|     } | |
| 
 | |
|     /** Table for application id. | |
|      * | |
|      * @param num Number of registered applications in total. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  TABLE | |
|      *   2 | |
|      *  APPID | |
|      *   70 | |
|      *      num | |
|      * </pre> | |
|      */ | |
|     void tableAppid( int num ) const | |
|     { | |
|         table( "APPID", num, 9 ); | |
|     } | |
| 
 | |
|     /** Table for text style. | |
|      * | |
|      * @param num Number of text styles. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  TABLE | |
|      *   2 | |
|      *  STYLE | |
|      *   70 | |
|      *      num | |
|      * </pre> | |
|      */ | |
|     void tableStyle( int num ) const | |
|     { | |
|         table( "STYLE", num, 3 ); | |
|     } | |
| 
 | |
|     /** | |
|      * End of a table. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  ENDTAB | |
|      * </pre> | |
|      */ | |
|     void tableEnd() const | |
|     { | |
|         dxfString( 0, "ENDTAB" ); | |
|     } | |
| 
 | |
|     /** | |
|      * End of the DXF file. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  EOF | |
|      * </pre> | |
|      */ | |
|     void dxfEOF() const | |
|     { | |
|         dxfString( 0, "EOF" ); | |
|     } | |
| 
 | |
|     /** | |
|      * Comment. | |
|      * | |
|      * <pre> | |
|      *  999 | |
|      *  text | |
|      * </pre> | |
|      */ | |
|     void comment( const char* text ) const | |
|     { | |
|         dxfString( 999, text ); | |
|     } | |
| 
 | |
|     /** | |
|      * Entity. | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  entTypeName | |
|      * </pre> | |
|      * | |
|      * @return Unique handle or 0. | |
|      */ | |
|     void entity( const char* entTypeName ) const | |
|     { | |
|         dxfString( 0, entTypeName ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             handle(); | |
|         } | |
|     } | |
| 
 | |
|     /** | |
|      * Attributes of an entity. | |
|      * | |
|      * <pre> | |
|      *   8 | |
|      *  layer | |
|      *  62 | |
|      *  color | |
|      *  39 | |
|      *  width | |
|      *   6 | |
|      *  linetype | |
|      * </pre> | |
|      */ | |
|     void entityAttributes( const DL_Attributes& attrib ) const | |
|     { | |
|         // layer name: | |
|         dxfString( 8, attrib.getLayer() ); | |
| 
 | |
|         // R12 doesn't accept BYLAYER values. The value has to be missing | |
|         // in that case. | |
|         if( version>=DL_VERSION_2000 || attrib.getColor()!=256 ) | |
|         { | |
|             dxfInt( 62, attrib.getColor() ); | |
|         } | |
| 
 | |
|         if( version>=DL_VERSION_2000 && attrib.getColor24()!=-1 ) | |
|         { | |
|             dxfInt( 420, attrib.getColor24() ); | |
|         } | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             dxfInt( 370, attrib.getWidth() ); | |
|         } | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             dxfReal( 48, attrib.getLinetypeScale() ); | |
|         } | |
| 
 | |
|         std::string linetype = attrib.getLinetype(); | |
|         std::transform( linetype.begin(), linetype.end(), linetype.begin(), ::toupper ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 || linetype=="BYLAYER" ) | |
|         { | |
|             dxfString( 6, attrib.getLinetype() ); | |
|         } | |
|     } | |
| 
 | |
|     /** | |
|      * Subclass. | |
|      */ | |
|     void subClass( const char* sub ) const | |
|     { | |
|         dxfString( 100, sub ); | |
|     } | |
| 
 | |
|     /** | |
|      * Layer (must be in the TABLES section LAYER). | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  LAYER | |
|      * </pre> | |
|      */ | |
|     void tableLayerEntry( unsigned long int h = 0 )  const | |
|     { | |
|         dxfString( 0, "LAYER" ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             if( h==0 ) | |
|             { | |
|                 handle(); | |
|             } | |
|             else | |
|             { | |
|                 dxfHex( 5, h ); | |
|             } | |
| 
 | |
|             dxfString( 100, "AcDbSymbolTableRecord" ); | |
|             dxfString( 100, "AcDbLayerTableRecord" ); | |
|         } | |
|     } | |
| 
 | |
|     /** | |
|      * Line type (must be in the TABLES section LTYPE). | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  LTYPE | |
|      * </pre> | |
|      */ | |
|     void tableLinetypeEntry( unsigned long int h = 0 )  const | |
|     { | |
|         dxfString( 0, "LTYPE" ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             if( h==0 ) | |
|             { | |
|                 handle(); | |
|             } | |
|             else | |
|             { | |
|                 dxfHex( 5, h ); | |
|             } | |
| 
 | |
|             // dxfHex(330, 0x5); | |
|             dxfString( 100, "AcDbSymbolTableRecord" ); | |
|             dxfString( 100, "AcDbLinetypeTableRecord" ); | |
|         } | |
|     } | |
| 
 | |
|     /** | |
|      * Appid (must be in the TABLES section APPID). | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  APPID | |
|      * </pre> | |
|      */ | |
|     void tableAppidEntry( unsigned long int h = 0 )  const | |
|     { | |
|         dxfString( 0, "APPID" ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             if( h==0 ) | |
|             { | |
|                 handle(); | |
|             } | |
|             else | |
|             { | |
|                 dxfHex( 5, h ); | |
|             } | |
| 
 | |
|             // dxfHex(330, 0x9); | |
|             dxfString( 100, "AcDbSymbolTableRecord" ); | |
|             dxfString( 100, "AcDbRegAppTableRecord" ); | |
|         } | |
|     } | |
| 
 | |
|     /** | |
|      * Block (must be in the section BLOCKS). | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  BLOCK | |
|      * </pre> | |
|      */ | |
|     void sectionBlockEntry( unsigned long int h = 0 )  const | |
|     { | |
|         dxfString( 0, "BLOCK" ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             if( h==0 ) | |
|             { | |
|                 handle(); | |
|             } | |
|             else | |
|             { | |
|                 dxfHex( 5, h ); | |
|             } | |
| 
 | |
|             // dxfHex(330, blockHandle); | |
|             dxfString( 100, "AcDbEntity" ); | |
| 
 | |
|             if( h==0x1C ) | |
|             { | |
|                 dxfInt( 67, 1 ); | |
|             } | |
| 
 | |
|             dxfString( 8, "0" );                 // TODO: Layer for block | |
|             dxfString( 100, "AcDbBlockBegin" ); | |
|         } | |
|     } | |
| 
 | |
|     /** | |
|      * End of Block (must be in the section BLOCKS). | |
|      * | |
|      * <pre> | |
|      *   0 | |
|      *  ENDBLK | |
|      * </pre> | |
|      */ | |
|     void sectionBlockEntryEnd( unsigned long int h = 0 )  const | |
|     { | |
|         dxfString( 0, "ENDBLK" ); | |
| 
 | |
|         if( version>=DL_VERSION_2000 ) | |
|         { | |
|             if( h==0 ) | |
|             { | |
|                 handle(); | |
|             } | |
|             else | |
|             { | |
|                 dxfHex( 5, h ); | |
|             } | |
| 
 | |
|             // dxfHex(330, blockHandle); | |
|             dxfString( 100, "AcDbEntity" ); | |
| 
 | |
|             if( h==0x1D ) | |
|             { | |
|                 dxfInt( 67, 1 ); | |
|             } | |
| 
 | |
|             dxfString( 8, "0" );                 // TODO: Layer for block | |
|             dxfString( 100, "AcDbBlockEnd" ); | |
|         } | |
|     } | |
| 
 | |
|     void color( int col = 256 ) const | |
|     { | |
|         dxfInt( 62, col ); | |
|     } | |
| 
 | |
|     void linetype( const char* lt ) const | |
|     { | |
|         dxfString( 6, lt ); | |
|     } | |
| 
 | |
|     void linetypeScale( double scale ) const | |
|     { | |
|         dxfReal( 48, scale ); | |
|     } | |
| 
 | |
|     void lineWeight( int lw ) const | |
|     { | |
|         dxfInt( 370, lw ); | |
|     } | |
| 
 | |
|     void coord( int gc, double x, double y, double z = 0 ) const | |
|     { | |
|         dxfReal( gc, x ); | |
|         dxfReal( gc + 10, y ); | |
|         dxfReal( gc + 20, z ); | |
|     } | |
| 
 | |
|     void coordTriplet( int gc, const double* value ) const | |
|     { | |
|         if( value ) | |
|         { | |
|             dxfReal( gc, *value++ ); | |
|             dxfReal( gc + 10, *value++ ); | |
|             dxfReal( gc + 20, *value++ ); | |
|         } | |
|     } | |
| 
 | |
|     void resetHandle() const | |
|     { | |
|         m_handle = 1; | |
|     } | |
| 
 | |
|     /** | |
|      * Writes a unique handle and returns it. | |
|      */ | |
|     unsigned long handle( int gc = 5 ) const | |
|     { | |
|         // handle has to be hex | |
|         dxfHex( gc, m_handle ); | |
|         return m_handle++; | |
|     } | |
| 
 | |
|     /** | |
|      * @return Next handle that will be written. | |
|      */ | |
|     unsigned long getNextHandle() const | |
|     { | |
|         return m_handle; | |
|     } | |
| 
 | |
|     /** | |
|      * Must be overwritten by the implementing class to write a | |
|      * real value to the file. | |
|      * | |
|      * @param gc Group code. | |
|      * @param value The real value. | |
|      */ | |
|     virtual void dxfReal( int gc, double value ) const = 0; | |
| 
 | |
|     /** | |
|      * Must be overwritten by the implementing class to write an | |
|      * int value to the file. | |
|      * | |
|      * @param gc Group code. | |
|      * @param value The int value. | |
|      */ | |
|     virtual void dxfInt( int gc, int value ) const = 0; | |
| 
 | |
|     /** | |
|      * Can be overwritten by the implementing class to write a | |
|      * bool value to the file. | |
|      * | |
|      * @param gc Group code. | |
|      * @param value The bool value. | |
|      */ | |
|     virtual void dxfBool( int gc, bool value ) const | |
|     { | |
|         dxfInt( gc, (int) value ); | |
|     } | |
| 
 | |
|     /** | |
|      * Must be overwritten by the implementing class to write an | |
|      * int value (hex) to the file. | |
|      * | |
|      * @param gc Group code. | |
|      * @param value The int value. | |
|      */ | |
|     virtual void dxfHex( int gc, int value ) const = 0; | |
| 
 | |
|     /** | |
|      * Must be overwritten by the implementing class to write a | |
|      * string to the file. | |
|      * | |
|      * @param gc Group code. | |
|      * @param value The string. | |
|      */ | |
|     virtual void dxfString( int gc, const char* value ) const = 0; | |
| 
 | |
|     /** | |
|      * Must be overwritten by the implementing class to write a | |
|      * string to the file. | |
|      * | |
|      * @param gc Group code. | |
|      * @param value The string. | |
|      */ | |
|     virtual void dxfString( int gc, const std::string& value ) const = 0; | |
| 
 | |
| protected: | |
|     mutable unsigned long   m_handle; | |
|     mutable unsigned long   modelSpaceHandle; | |
|     mutable unsigned long   paperSpaceHandle; | |
|     mutable unsigned long   paperSpace0Handle; | |
| 
 | |
|     /** | |
|      * DXF version to be created. | |
|      */ | |
|     DL_Codes::version version; | |
| 
 | |
| private: | |
| }; | |
| 
 | |
| #endif
 |