kicad/thirdparty/dxflib_qcad/dl_writer.h

702 lines
13 KiB
C++

/****************************************************************************
** 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