#include "format-dxf.h"
#include "helpers-misc.h"
#include "emb-hash.h"
#include "emb-logging.h"
#include "geom-arc.h"
/*#include "geom-line.h" */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* DXF Version Identifiers */
#define DXF_VERSION_R10 "AC1006"
#define DXF_VERSION_R11 "AC1009"
#define DXF_VERSION_R12 "AC1009"
#define DXF_VERSION_R13 "AC1012"
#define DXF_VERSION_R14 "AC1014"
#define DXF_VERSION_R15 "AC1015"
#define DXF_VERSION_R18 "AC1018"
#define DXF_VERSION_R21 "AC1021"
#define DXF_VERSION_R24 "AC1024"
#define DXF_VERSION_R27 "AC1027"
#define DXF_VERSION_2000 "AC1015"
#define DXF_VERSION_2002 "AC1015"
#define DXF_VERSION_2004 "AC1018"
#define DXF_VERSION_2006 "AC1018"
#define DXF_VERSION_2007 "AC1021"
#define DXF_VERSION_2009 "AC1021"
#define DXF_VERSION_2010 "AC1024"
#define DXF_VERSION_2013 "AC1027"
/* Based on the DraftSight color table */
static const unsigned char _dxfColorTable[][3] = {
{ 0, 0, 0 }, /* '0' (BYBLOCK) */
{ 255, 0, 0 }, /* '1' (red) */
{ 255, 255, 0 }, /* '2' (yellow) */
{ 0, 255, 0 }, /* '3' (green) */
{ 0, 255, 255 }, /* '4' (cyan) */
{ 0, 0, 255 }, /* '5' (blue) */
{ 255, 0, 255 }, /* '6' (magenta) */
{ 255, 255, 255 }, /* '7' (white) */
{ 128, 128, 128 }, /* '8' (dark gray) */
{ 192, 192, 192 }, /* '9' (light gray) */
{ 255, 0, 0 }, /* '10' */
{ 255, 127, 127 }, /* '11' */
{ 204, 0, 0 }, /* '12' */
{ 204, 102, 102 }, /* '13' */
{ 153, 0, 0 }, /* '14' */
{ 153, 76, 76 }, /* '15' */
{ 127, 0, 0 }, /* '16' */
{ 127, 63, 63 }, /* '17' */
{ 76, 0, 0 }, /* '18' */
{ 76, 38, 38 }, /* '19' */
{ 255, 63, 0 }, /* '20' */
{ 255, 159, 127 }, /* '21' */
{ 204, 51, 0 }, /* '22' */
{ 204, 127, 102 }, /* '23' */
{ 153, 38, 0 }, /* '24' */
{ 153, 95, 76 }, /* '25' */
{ 127, 31, 0 }, /* '26' */
{ 127, 79, 63 }, /* '27' */
{ 76, 19, 0 }, /* '28' */
{ 76, 47, 38 }, /* '29' */
{ 255, 127, 0 }, /* '30' */
{ 255, 191, 127 }, /* '31' */
{ 204, 102, 0 }, /* '32' */
{ 204, 153, 102 }, /* '33' */
{ 153, 76, 0 }, /* '34' */
{ 153, 114, 76 }, /* '35' */
{ 127, 63, 0 }, /* '36' */
{ 127, 95, 63 }, /* '37' */
{ 76, 38, 0 }, /* '38' */
{ 76, 57, 38 }, /* '39' */
{ 255, 191, 0 }, /* '40' */
{ 255, 223, 127 }, /* '41' */
{ 204, 153, 0 }, /* '42' */
{ 204, 178, 102 }, /* '43' */
{ 153, 114, 0 }, /* '44' */
{ 153, 133, 76 }, /* '45' */
{ 127, 95, 0 }, /* '46' */
{ 127, 111, 63 }, /* '47' */
{ 76, 57, 0 }, /* '48' */
{ 76, 66, 38 }, /* '49' */
{ 255, 255, 0 }, /* '50' */
{ 255, 255, 127 }, /* '51' */
{ 204, 204, 0 }, /* '52' */
{ 204, 204, 102 }, /* '53' */
{ 153, 153, 0 }, /* '54' */
{ 153, 153, 76 }, /* '55' */
{ 127, 127, 0 }, /* '56' */
{ 127, 127, 63 }, /* '57' */
{ 76, 76, 0 }, /* '58' */
{ 76, 76, 38 }, /* '59' */
{ 191, 255, 0 }, /* '60' */
{ 223, 255, 127 }, /* '61' */
{ 153, 204, 0 }, /* '62' */
{ 178, 204, 102 }, /* '63' */
{ 114, 153, 0 }, /* '64' */
{ 133, 153, 76 }, /* '65' */
{ 95, 127, 0 }, /* '66' */
{ 111, 127, 63 }, /* '67' */
{ 57, 76, 0 }, /* '68' */
{ 66, 76, 38 }, /* '69' */
{ 127, 255, 0 }, /* '70' */
{ 191, 255, 127 }, /* '71' */
{ 102, 204, 0 }, /* '72' */
{ 153, 204, 102 }, /* '73' */
{ 76, 153, 0 }, /* '74' */
{ 114, 153, 76 }, /* '75' */
{ 63, 127, 0 }, /* '76' */
{ 95, 127, 63 }, /* '77' */
{ 38, 76, 0 }, /* '78' */
{ 57, 76, 38 }, /* '79' */
{ 63, 255, 0 }, /* '80' */
{ 159, 255, 127 }, /* '81' */
{ 51, 204, 0 }, /* '82' */
{ 127, 204, 102 }, /* '83' */
{ 38, 153, 0 }, /* '84' */
{ 95, 153, 76 }, /* '85' */
{ 31, 127, 0 }, /* '86' */
{ 79, 127, 63 }, /* '87' */
{ 19, 76, 0 }, /* '88' */
{ 47, 76, 38 }, /* '89' */
{ 0, 255, 0 }, /* '90' */
{ 127, 255, 127 }, /* '91' */
{ 0, 204, 0 }, /* '92' */
{ 102, 204, 102 }, /* '93' */
{ 0, 153, 0 }, /* '94' */
{ 76, 153, 76 }, /* '95' */
{ 0, 127, 0 }, /* '96' */
{ 63, 127, 63 }, /* '97' */
{ 0, 76, 0 }, /* '98' */
{ 38, 76, 38 }, /* '99' */
{ 0, 255, 63 }, /* '100' */
{ 127, 255, 159 }, /* '101' */
{ 0, 204, 51 }, /* '102' */
{ 102, 204, 127 }, /* '103' */
{ 0, 153, 38 }, /* '104' */
{ 76, 153, 95 }, /* '105' */
{ 0, 127, 31 }, /* '106' */
{ 63, 127, 79 }, /* '107' */
{ 0, 76, 19 }, /* '108' */
{ 38, 76, 47 }, /* '109' */
{ 0, 255, 127 }, /* '110' */
{ 127, 255, 191 }, /* '111' */
{ 0, 204, 102 }, /* '112' */
{ 102, 204, 153 }, /* '113' */
{ 0, 153, 76 }, /* '114' */
{ 76, 153, 114 }, /* '115' */
{ 0, 127, 63 }, /* '116' */
{ 63, 127, 95 }, /* '117' */
{ 0, 76, 38 }, /* '118' */
{ 38, 76, 57 }, /* '119' */
{ 0, 255, 191 }, /* '120' */
{ 127, 255, 223 }, /* '121' */
{ 0, 204, 153 }, /* '122' */
{ 102, 204, 178 }, /* '123' */
{ 0, 153, 114 }, /* '124' */
{ 76, 153, 133 }, /* '125' */
{ 0, 127, 95 }, /* '126' */
{ 63, 127, 111 }, /* '127' */
{ 0, 76, 57 }, /* '128' */
{ 38, 76, 66 }, /* '129' */
{ 0, 255, 255 }, /* '130' */
{ 127, 255, 255 }, /* '131' */
{ 0, 204, 204 }, /* '132' */
{ 102, 204, 204 }, /* '133' */
{ 0, 153, 153 }, /* '134' */
{ 76, 153, 153 }, /* '135' */
{ 0, 127, 127 }, /* '136' */
{ 63, 127, 127 }, /* '137' */
{ 0, 76, 76 }, /* '138' */
{ 38, 76, 76 }, /* '139' */
{ 0, 191, 255 }, /* '140' */
{ 127, 223, 255 }, /* '141' */
{ 0, 153, 204 }, /* '142' */
{ 102, 178, 204 }, /* '143' */
{ 0, 114, 153 }, /* '144' */
{ 76, 133, 153 }, /* '145' */
{ 0, 95, 127 }, /* '146' */
{ 63, 111, 127 }, /* '147' */
{ 0, 57, 76 }, /* '148' */
{ 38, 66, 76 }, /* '149' */
{ 0, 127, 255 }, /* '150' */
{ 127, 191, 255 }, /* '151' */
{ 0, 102, 204 }, /* '152' */
{ 102, 153, 204 }, /* '153' */
{ 0, 76, 153 }, /* '154' */
{ 76, 114, 153 }, /* '155' */
{ 0, 63, 127 }, /* '156' */
{ 63, 95, 127 }, /* '157' */
{ 0, 38, 76 }, /* '158' */
{ 38, 57, 76 }, /* '159' */
{ 0, 63, 255 }, /* '160' */
{ 127, 159, 255 }, /* '161' */
{ 0, 51, 204 }, /* '162' */
{ 102, 127, 204 }, /* '163' */
{ 0, 38, 153 }, /* '164' */
{ 76, 95, 153 }, /* '165' */
{ 0, 31, 127 }, /* '166' */
{ 63, 79, 127 }, /* '167' */
{ 0, 19, 76 }, /* '168' */
{ 38, 47, 76 }, /* '169' */
{ 0, 0, 255 }, /* '170' */
{ 127, 127, 255 }, /* '171' */
{ 0, 0, 204 }, /* '172' */
{ 102, 102, 204 }, /* '173' */
{ 0, 0, 153 }, /* '174' */
{ 76, 76, 153 }, /* '175' */
{ 0, 0, 127 }, /* '176' */
{ 63, 63, 127 }, /* '177' */
{ 0, 0, 76 }, /* '178' */
{ 38, 38, 76 }, /* '179' */
{ 63, 0, 255 }, /* '180' */
{ 159, 127, 255 }, /* '181' */
{ 51, 0, 204 }, /* '182' */
{ 127, 102, 204 }, /* '183' */
{ 38, 0, 153 }, /* '184' */
{ 95, 76, 153 }, /* '185' */
{ 31, 0, 127 }, /* '186' */
{ 79, 63, 127 }, /* '187' */
{ 19, 0, 76 }, /* '188' */
{ 47, 38, 76 }, /* '189' */
{ 127, 0, 255 }, /* '190' */
{ 191, 127, 255 }, /* '191' */
{ 102, 0, 204 }, /* '192' */
{ 153, 102, 204 }, /* '193' */
{ 76, 0, 153 }, /* '194' */
{ 114, 76, 153 }, /* '195' */
{ 63, 0, 127 }, /* '196' */
{ 95, 63, 127 }, /* '197' */
{ 38, 0, 76 }, /* '198' */
{ 57, 38, 76 }, /* '199' */
{ 191, 0, 255 }, /* '200' */
{ 223, 127, 255 }, /* '201' */
{ 153, 0, 204 }, /* '202' */
{ 178, 102, 204 }, /* '203' */
{ 114, 0, 153 }, /* '204' */
{ 133, 76, 153 }, /* '205' */
{ 95, 0, 127 }, /* '206' */
{ 111, 63, 127 }, /* '207' */
{ 57, 0, 76 }, /* '208' */
{ 66, 38, 76 }, /* '209' */
{ 255, 0, 255 }, /* '210' */
{ 255, 127, 255 }, /* '211' */
{ 204, 0, 204 }, /* '212' */
{ 204, 102, 204 }, /* '213' */
{ 153, 0, 153 }, /* '214' */
{ 153, 76, 153 }, /* '215' */
{ 127, 0, 127 }, /* '216' */
{ 127, 63, 127 }, /* '217' */
{ 76, 0, 76 }, /* '218' */
{ 76, 38, 76 }, /* '219' */
{ 255, 0, 191 }, /* '220' */
{ 255, 127, 223 }, /* '221' */
{ 204, 0, 153 }, /* '222' */
{ 204, 102, 178 }, /* '223' */
{ 153, 0, 114 }, /* '224' */
{ 153, 76, 133 }, /* '225' */
{ 127, 0, 95 }, /* '226' */
{ 127, 63, 111 }, /* '227' */
{ 76, 0, 57 }, /* '228' */
{ 76, 38, 66 }, /* '229' */
{ 255, 0, 127 }, /* '230' */
{ 255, 127, 191 }, /* '231' */
{ 204, 0, 102 }, /* '232' */
{ 204, 102, 153 }, /* '233' */
{ 153, 0, 76 }, /* '234' */
{ 153, 76, 114 }, /* '235' */
{ 127, 0, 63 }, /* '236' */
{ 127, 63, 95 }, /* '237' */
{ 76, 0, 38 }, /* '238' */
{ 76, 38, 57 }, /* '239' */
{ 255, 0, 63 }, /* '240' */
{ 255, 127, 159 }, /* '241' */
{ 204, 0, 51 }, /* '242' */
{ 204, 102, 127 }, /* '243' */
{ 153, 0, 38 }, /* '244' */
{ 153, 76, 95 }, /* '245' */
{ 127, 0, 31 }, /* '246' */
{ 127, 63, 79 }, /* '247' */
{ 76, 0, 19 }, /* '248' */
{ 76, 38, 47 }, /* '249' */
{ 51, 51, 51 }, /* '250' */
{ 91, 91, 91 }, /* '251' */
{ 132, 132, 132 }, /* '252' */
{ 173, 173, 173 }, /* '253' */
{ 214, 214, 214 }, /* '254' */
{ 255, 255, 255 }, /* '255' */
{ 0, 0, 0 } /* '256' (BYLAYER) */
};
char* readLine(FILE* file)
{
char str[255];
/* TODO: replace all scanf code */
fscanf(file, "%s", str);
return lTrim(str, ' ');
}
/*! Reads a file with the given \a fileName and loads the data into \a pattern.
* Returns \c true if successful, otherwise returns \c false. */
int readDxf(EmbPattern* pattern, const char* fileName)
{
FILE* file = 0;
char* buff = "";
char* dxfVersion = "";
char* section = "";
char* tableName = "";
char* layerName = "";
char* entityType = "";
EmbHash* layerColorHash = 0; /* hash <layerName, EmbColor> */
int eof = 0; /* End Of File */
double bulge = 0.0, firstX = 0.0, firstY = 0.0, x = 0.0, y, prevX = 0.0, prevY = 0.0;
char firstStitch = 1;
char bulgeFlag = 0;
int fileLength = 0;
unsigned char colorNum = 0;
if(!pattern) { embLog_error("format-dxf.c readDxf(), pattern argument is null\n"); return 0; }
if(!fileName) { embLog_error("format-dxf.c readDxf(), fileName argument is null\n"); return 0; }
layerColorHash = embHash_create();
if(!layerColorHash) { embLog_error("format-dxf.c readDxf(), unable to allocate memory for layerColorHash\n"); return 0; }
file = fopen(fileName, "r");
if(!file)
{
embLog_error("format-dxf.c readDxf(), cannot open %s for reading\n", fileName);
return 0;
}
fseek(file, 0L, SEEK_END);
fileLength = ftell(file);
fseek(file, 0L, SEEK_SET);
while(ftell(file) < fileLength)
{
buff = readLine(file);
/*printf("%s\n", buff);*/
if( (!strcmp(buff, "HEADER")) ||
(!strcmp(buff, "CLASSES")) ||
(!strcmp(buff, "TABLES")) ||
(!strcmp(buff, "BLOCKS")) ||
(!strcmp(buff, "ENTITIES")) ||
(!strcmp(buff, "OBJECTS")) ||
(!strcmp(buff, "THUMBNAILIMAGE")))
{
section = buff;
printf("SECTION:%s\n", buff);
}
if(!strcmp(buff, "ENDSEC"))
{
section = "";
printf("ENDSEC:%s\n", buff);
}
if( (!strcmp(buff, "ARC")) ||
(!strcmp(buff, "CIRCLE")) ||
(!strcmp(buff, "ELLIPSE")) ||
(!strcmp(buff, "LINE")) ||
(!strcmp(buff, "LWPOLYLINE")) ||
(!strcmp(buff, "POINT")))
{
entityType = buff;
}
if(!strcmp(buff, "EOF"))
{
eof = 1;
}
if(!strcmp(section, "HEADER"))
{
if(!strcmp(buff, "$ACADVER"))
{
buff = readLine(file);
dxfVersion = readLine(file);
/* TODO: Allow these versions when POLYLINE is handled. */
if((!strcmp(dxfVersion, DXF_VERSION_R10))
|| (!strcmp(dxfVersion, DXF_VERSION_R11))
|| (!strcmp(dxfVersion, DXF_VERSION_R12))
|| (!strcmp(dxfVersion, DXF_VERSION_R13)))
return 0;
}
}
else if(!strcmp(section,"TABLES"))
{
if(!strcmp(buff,"ENDTAB"))
{
tableName = NULL;
}
if(tableName == NULL)
{
if(!strcmp(buff,"2")) /* Table Name */
{
tableName = readLine(file);
}
}
else if(!strcmp(tableName, "LAYER"))
{
/* Common Group Codes for Tables */
if(!strcmp(buff,"5")) /* Handle */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff,"330")) /* Soft Pointer */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff,"100")) /* Subclass Marker */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff,"70")) /* Number of Entries in Table */
{
buff = readLine(file);
continue;
}
/* The meaty stuff */
else if(!strcmp(buff,"2")) /* Layer Name */
{
layerName = readLine(file);
}
else if(!strcmp(buff,"62")) /* Color Number */
{
buff = readLine(file);
colorNum = atoi(buff);
/*
TODO: finish this
unsigned char colorNum = atoi(buff);
EmbColor* co = embColor_create(_dxfColorTable[colorNum][0], _dxfColorTable[colorNum][1], _dxfColorTable[colorNum][2]);
if(!co) { / TODO: error allocating memory for EmbColor return 0; }
printf("inserting:%s,%d,%d,%d\n", layerName, co->r, co->g, co->b);
if(embHash_insert(layerColorHash, emb_strdup(layerName), co))
{
TODO: log error: failed inserting into layerColorHash
}
*/
layerName = NULL;
}
}
}
else if(!strcmp(section,"ENTITIES"))
{
/* Common Group Codes for Entities */
if(!strcmp(buff, "5")) /* Handle */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff, "330")) /* Soft Pointer */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff, "100")) /* Subclass Marker */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff, "8")) /* Layer Name */
{
buff = readLine(file);
/* embPattern_changeColor(pattern, colorIndexMap[buff]); TODO: port to C */
continue;
}
if(!strcmp(entityType,"LWPOLYLINE"))
{
double* arcMidX = 0;
double* arcMidY = 0;
/* The not so important group codes */
if(!strcmp(buff, "90")) /* Vertices */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff,"70")) /* Polyline Flag */
{
buff = readLine(file);
continue;
}
/* TODO: Try to use the widths at some point */
else if(!strcmp(buff,"40")) /* Starting Width */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff,"41")) /* Ending Width */
{
buff = readLine(file);
continue;
}
else if(!strcmp(buff,"43")) /* Constant Width */
{
buff = readLine(file);
continue;
}
/* The meaty stuff */
else if(!strcmp(buff,"42")) /* Bulge */
{
buff = readLine(file);
bulge = atof(buff);
bulgeFlag = 1;
}
else if(!strcmp(buff,"10")) /* X */
{
buff = readLine(file);
x = atof(buff);
}
else if(!strcmp(buff,"20")) /* Y */
{
buff = readLine(file);
y = atof(buff);
if(bulgeFlag)
{
bulgeFlag = 0;
if(!getArcDataFromBulge(bulge, prevX, prevY, x, y, arcMidX, arcMidY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
{
/*TODO: error */
return 0;
}
if(firstStitch)
{
/* embPattern_addStitchAbs(pattern, x, y, TRIM, 1); TODO: Add moveTo point to embPath pointList */
}
/* embPattern_addStitchAbs(pattern, x, y, ARC, 1); TODO: Add arcTo point to embPath pointList */
}
else
{
/*if(firstStitch) embPattern_addStitchAbs(pattern, x, y, TRIM, 1); TODO: Add moveTo point to embPath pointList */
/*else embPattern_addStitchAbs(pattern, x, y, NORMAL, 1); TODO: Add lineTo point to embPath pointList */
}
prevX = x;
prevY = y;
if(firstStitch)
{
firstX = x;
firstY = y;
firstStitch = 0;
}
}
else if(!strcmp(buff,"0"))
{
entityType = NULL;
firstStitch = 1;
if(bulgeFlag)
{
bulgeFlag = 0;
if(!getArcDataFromBulge(bulge, prevX, prevY, firstX, firstY, arcMidX, arcMidY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
{
/*TODO: error */
return 0;
}
/* embPattern_addStitchAbs(pattern, prevX, prevY, ARC, 1); TODO: Add arcTo point to embPath pointList */
}
else
{
/* embPattern_addStitchAbs(pattern, firstX, firstY, NORMAL, 1); TODO: Add lineTo point to embPath pointList */
}
}
} /* end LWPOLYLINE */
} /* end ENTITIES section */
} /* end while loop */
fclose(file);
/*
EmbColor* testColor = 0;
testColor = embHash_value(layerColorHash, "OMEGA");
if(!testColor) printf("NULL POINTER!!!!!!!!!!!!!!\n");
else printf("LAYERCOLOR: %d,%d,%d\n", testColor->r, testColor->g, testColor->b);
*/
if(!eof)
{
/* NOTE: The EOF item must be present at the end of file to be considered a valid DXF file. */
embLog_error("format-dxf.c readDxf(), missing EOF at end of DXF file\n");
}
return eof;
}
/*! Writes the data from \a pattern to a file with the given \a fileName.
* Returns \c true if successful, otherwise returns \c false. */
int writeDxf(EmbPattern* pattern, const char* fileName)
{
if(!pattern) { embLog_error("format-dxf.c writeDxf(), pattern argument is null\n"); return 0; }
if(!fileName) { embLog_error("format-dxf.c writeDxf(), fileName argument is null\n"); return 0; }
return 0; /*TODO: finish writeDxf */
}
/* kate: bom off; indent-mode cstyle; indent-width 4; replace-trailing-space-save on; */