Fixed wrong use of g_error()
[dia.git] / plug-ins / dxf / dxf-import.c
blob1d968d3c80c5a364f16d8404b643899dce5dae94
1 /* -*- Mode: C; c-basic-offset: 4 -*- */
2 /* Dia -- an diagram creation/manipulation program
3 * Copyright (C) 1998 Alexander Larsson
5 * dxf-import.c: dxf import filter for dia
6 * Copyright (C) 2000 Steffen Macke
7 * Copyright (C) 2002 Angus Ainslie
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <stdio.h>
29 #include <string.h>
30 #include <math.h>
31 #include <glib.h>
32 #include <stdlib.h>
33 #include <locale.h>
35 #include "intl.h"
36 #include "message.h"
37 #include "geometry.h"
38 #include "diarenderer.h"
39 #include "filter.h"
40 #include "object.h"
41 #include "properties.h"
42 #include "propinternals.h"
43 #include "autocad_pal.h"
45 #include "group.h"
46 #include "create.h"
47 #include "attributes.h"
49 static real coord_scale = 1.0, measure_scale = 1.0;
50 static real text_scale = 1.0;
52 #define WIDTH_SCALE measure_scale
53 #define DEFAULT_LINE_WIDTH 0.001
55 Point extent_min, extent_max;
56 Point limit_min, limit_max;
58 /* maximum line length */
59 #define DXF_LINE_LENGTH 256
61 typedef struct layer_data_tag
63 char layerName[256];
64 int acad_colour;
65 } layer_data_type;
67 typedef struct _DxfData
69 char code[DXF_LINE_LENGTH];
70 char value[DXF_LINE_LENGTH];
71 } DxfData;
73 gboolean import_dxf(const gchar *filename, DiagramData *dia, void* user_data);
74 gboolean read_dxf_codes(FILE *filedxf, DxfData *data);
75 DiaObject *read_entity_line_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
76 DiaObject *read_entity_circle_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
77 DiaObject *read_entity_ellipse_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
78 DiaObject *read_entity_arc_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
79 DiaObject *read_entity_solid_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
80 DiaObject *read_entity_polyline_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
81 DiaObject *read_entity_text_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
82 void read_entity_measurement_dxf(FILE *filedxf, DxfData *data,
83 DiagramData *dia);
84 void read_entity_scale_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
85 void read_entity_textsize_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
86 void read_entity_mesurement_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
87 void read_table_layer_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
88 void read_section_header_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
89 void read_section_classes_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
90 void read_section_tables_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
91 void read_section_entities_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
92 void read_section_blocks_dxf(FILE *filedxf, DxfData *data, DiagramData *dia);
93 Layer *layer_find_by_name(char *layername, DiagramData *dia);
94 LineStyle get_dia_linestyle_dxf(char *dxflinestyle);
96 /* returns the layer with the given name */
97 /* TODO: merge this with other layer code? */
98 Layer *layer_find_by_name(char *layername, DiagramData *dia)
100 Layer *matching_layer, *layer;
101 int i;
103 matching_layer = NULL;
105 for (i=0; i<dia->layers->len; i++) {
106 layer = (Layer *)g_ptr_array_index(dia->layers, i);
107 if(strcmp(layer->name, layername) == 0) {
108 matching_layer = layer;
109 break;
113 if( matching_layer == NULL )
115 matching_layer = new_layer(g_strdup( layername ), dia);
116 data_add_layer(dia, matching_layer);
119 return matching_layer;
122 /* returns the matching dia linestyle for a given dxf linestyle */
123 /* if no matching style is found, LINESTYLE solid is returned as a default */
124 LineStyle get_dia_linestyle_dxf(char *dxflinestyle) {
125 if(strcmp(dxflinestyle, "DASH") == 0) {
126 return LINESTYLE_DASHED;
128 if(strcmp(dxflinestyle, "DASHDOT") == 0){
129 return LINESTYLE_DASH_DOT;
131 if(strcmp(dxflinestyle, "DOT") == 0){
132 return LINESTYLE_DOTTED;
134 return LINESTYLE_SOLID;
137 static PropDescription dxf_prop_descs[] = {
138 { "start_point", PROP_TYPE_POINT },
139 { "end_point", PROP_TYPE_POINT },
140 { "line_colour", PROP_TYPE_COLOUR },
141 { "line_width", PROP_TYPE_REAL },
142 { "line_style", PROP_TYPE_LINESTYLE},
143 PROP_DESC_END};
146 /* reads a line entity from the dxf file and creates a line object in dia*/
147 DiaObject *read_entity_line_dxf(FILE *filedxf, DxfData *data, DiagramData *dia){
148 int codedxf;
149 char *old_locale;
151 /* line data */
152 Point start, end;
154 DiaObjectType *otype = object_get_type("Standard - Line");
155 Handle *h1, *h2;
157 DiaObject *line_obj;
158 Color line_colour = { 0.0, 0.0, 0.0 };
159 GPtrArray *props;
160 PointProperty *ptprop;
161 LinestyleProperty *lsprop;
162 ColorProperty *cprop;
163 RealProperty *rprop;
165 real line_width = DEFAULT_LINE_WIDTH;
166 LineStyle style = LINESTYLE_SOLID;
167 Layer *layer = NULL;
169 old_locale = setlocale(LC_NUMERIC, "C");
170 do {
171 if(read_dxf_codes(filedxf, data) == FALSE){
172 setlocale(LC_NUMERIC, old_locale);
173 return( NULL );
175 codedxf = atoi(data->code);
176 switch(codedxf){
177 case 6: style = get_dia_linestyle_dxf(data->value);
178 break;
179 case 8: layer = layer_find_by_name(data->value, dia);
180 break;
181 case 10:
182 start.x = atof(data->value) * coord_scale * measure_scale;
183 break;
184 case 11:
185 end.x = atof(data->value) * coord_scale * measure_scale;
186 break;
187 case 20:
188 start.y = (-1)*atof(data->value) * coord_scale * measure_scale;
189 break;
190 case 21:
191 end.y = (-1)*atof(data->value) * coord_scale * measure_scale;
192 break;
193 case 39:
194 line_width = atof(data->value) * WIDTH_SCALE;
195 /*printf( "line width %f\n", line_width ); */
196 break;
198 } while(codedxf != 0);
199 setlocale(LC_NUMERIC, old_locale);
201 line_obj = otype->ops->create(&start, otype->default_user_data,
202 &h1, &h2);
203 layer_add_object(layer, line_obj);
205 props = prop_list_from_descs(dxf_prop_descs,pdtpp_true);
206 g_assert(props->len == 5);
208 ptprop = g_ptr_array_index(props,0);
209 ptprop->point_data = start;
211 ptprop = g_ptr_array_index(props,1);
212 ptprop->point_data = end;
214 cprop = g_ptr_array_index(props,2);
215 cprop->color_data = line_colour;
217 rprop = g_ptr_array_index(props,3);
218 rprop->real_data = line_width;
220 lsprop = g_ptr_array_index(props,4);
221 lsprop->style = style;
222 lsprop->dash = 1.0;
224 line_obj->ops->set_props(line_obj, props);
226 prop_list_free(props);
228 return( line_obj );
231 static PropDescription dxf_solid_prop_descs[] = {
232 { "line_colour", PROP_TYPE_COLOUR },
233 { "line_width", PROP_TYPE_REAL },
234 { "line_style", PROP_TYPE_LINESTYLE },
235 { "fill_colour", PROP_TYPE_COLOUR },
236 { "show_background", PROP_TYPE_BOOL },
237 PROP_DESC_END};
239 /* reads a solid entity from the dxf file and creates a polygon object in dia*/
240 DiaObject *read_entity_solid_dxf(FILE *filedxf, DxfData *data, DiagramData *dia)
242 int codedxf;
243 char *old_locale;
245 /* polygon data */
246 Point p[4];
248 DiaObjectType *otype = object_get_type("Standard - Polygon");
249 Handle *h1, *h2;
251 DiaObject *polygon_obj;
252 MultipointCreateData *pcd;
254 Color fill_colour = { 0.5, 0.5, 0.5 };
256 GPtrArray *props;
257 LinestyleProperty *lsprop;
258 ColorProperty *cprop, *fprop;
259 RealProperty *rprop;
260 BoolProperty *bprop;
262 real line_width = 0.001;
263 LineStyle style = LINESTYLE_SOLID;
264 Layer *layer = NULL;
265 unsigned char colour;
267 /* printf( "Solid " ); */
269 old_locale = setlocale(LC_NUMERIC, "C");
270 do {
271 if(read_dxf_codes(filedxf, data) == FALSE){
272 setlocale(LC_NUMERIC, old_locale);
273 return( NULL );
275 codedxf = atoi(data->code);
276 switch(codedxf){
277 case 6:
278 style = get_dia_linestyle_dxf(data->value);
279 break;
280 case 8:
281 layer = layer_find_by_name(data->value, dia);
282 /*printf( "layer: %s ", data->value );*/
283 break;
284 case 10:
285 p[0].x = atof(data->value) * coord_scale * measure_scale;
286 /*printf( "P0.x: %f ", p[0].x );*/
287 break;
288 case 11:
289 p[1].x = atof(data->value) * coord_scale * measure_scale;
290 /*printf( "P1.x: %f ", p[1].x );*/
291 break;
292 case 12:
293 p[2].x = atof(data->value) * coord_scale * measure_scale;
294 /*printf( "P2.x: %f ", p[2].x );*/
295 break;
296 case 13:
297 p[3].x = atof(data->value) * coord_scale * measure_scale;
298 /*printf( "P3.x: %f ", p[3].x );*/
299 break;
300 case 20:
301 p[0].y = (-1)*atof(data->value) * coord_scale * measure_scale;
302 /*printf( "P0.y: %f ", p[0].y );*/
303 break;
304 case 21:
305 p[1].y = (-1)*atof(data->value) * coord_scale * measure_scale;
306 /*printf( "P1.y: %f ", p[1].y );*/
307 break;
308 case 22:
309 p[2].y = (-1)*atof(data->value) * coord_scale * measure_scale;
310 /*printf( "P2.y: %f ", p[2].y );*/
311 break;
312 case 23:
313 p[3].y = (-1)*atof(data->value) * coord_scale * measure_scale;
314 /*printf( "P3.y: %f\n", p[3].y );*/
315 break;
316 case 39:
317 line_width = atof(data->value) * WIDTH_SCALE;
318 /*printf( "width %f\n", line_width );*/
319 break;
320 case 62:
321 colour = atoi(data->value);
322 fill_colour.red = acad_pal[colour].r / 255.0;
323 fill_colour.green = acad_pal[colour].g / 255.0;
324 fill_colour.blue = acad_pal[colour].b / 255.0;
325 /* printf( "acad colour %d %d %d\n", acad_pal[colour].r, acad_pal[colour].g, acad_pal[colour].b );
326 printf( "fill colour %f %f %f\n", fill_colour.red, fill_colour.green, fill_colour.blue );*/
327 break;
329 } while(codedxf != 0);
330 setlocale(LC_NUMERIC, old_locale);
332 pcd = g_new( MultipointCreateData, 1);
334 if( p[2].x != p[3].x && p[2].y != p[3].y )
335 pcd->num_points = 4;
336 else
337 pcd->num_points = 3;
339 pcd->points = g_new( Point, pcd->num_points );
341 memcpy( pcd->points, p, sizeof( Point ) * pcd->num_points );
343 polygon_obj = otype->ops->create( NULL, pcd, &h1, &h2 );
345 layer_add_object( layer, polygon_obj );
347 props = prop_list_from_descs( dxf_solid_prop_descs, pdtpp_true );
348 g_assert(props->len == 5);
350 cprop = g_ptr_array_index( props,0 );
351 cprop->color_data = fill_colour;
353 rprop = g_ptr_array_index( props,1 );
354 rprop->real_data = line_width;
356 lsprop = g_ptr_array_index( props,2 );
357 lsprop->style = style;
358 lsprop->dash = 1.0;
360 fprop = g_ptr_array_index( props, 3 );
361 fprop->color_data = fill_colour;
363 bprop = g_ptr_array_index( props, 4 );
364 bprop->bool_data = TRUE;
366 polygon_obj->ops->set_props( polygon_obj, props );
368 prop_list_free(props);
370 return( polygon_obj );
373 static PropDescription dxf_polyline_prop_descs[] = {
374 { "line_colour", PROP_TYPE_COLOUR },
375 { "line_width", PROP_TYPE_REAL },
376 { "line_style", PROP_TYPE_LINESTYLE },
377 PROP_DESC_END};
379 static int is_equal( double a, double b )
381 double epsilon = 0.001;
383 if( a == b )
384 return( 1 );
386 if(( a + epsilon ) > b && ( a - epsilon ) < b )
387 return( 1 );
389 return( 0 );
392 /* reads a polyline entity from the dxf file and creates a polyline object in dia*/
393 DiaObject *read_entity_polyline_dxf(FILE *filedxf, DxfData *data, DiagramData *dia)
395 int codedxf, i;
396 char *old_locale;
398 /* polygon data */
399 Point *p = NULL, start, end, center;
401 DiaObjectType *otype = object_get_type("Standard - PolyLine");
402 Handle *h1, *h2;
404 DiaObject *polyline_obj;
405 MultipointCreateData *pcd;
407 Color line_colour = { 0.0, 0.0, 0.0 };
409 GPtrArray *props;
410 LinestyleProperty *lsprop;
411 ColorProperty *cprop;
412 RealProperty *rprop;
414 real line_width = DEFAULT_LINE_WIDTH;
415 real radius, start_angle = 0;
416 LineStyle style = LINESTYLE_SOLID;
417 Layer *layer = NULL;
418 unsigned char colour, closed = 0;
419 int points = 0;
421 old_locale = setlocale(LC_NUMERIC, "C");
422 do {
423 if(read_dxf_codes(filedxf, data) == FALSE){
424 setlocale(LC_NUMERIC, old_locale);
425 return( NULL );
427 codedxf = atoi(data->code);
428 switch(codedxf){
429 case 0:
430 if( !strcmp( data->value, "VERTEX" ))
432 points++;
434 p = realloc( p, sizeof( Point ) * points );
436 /*printf( "Vertex %d\n", points );*/
440 case 6:
441 style = get_dia_linestyle_dxf(data->value);
442 break;
443 case 8:
444 layer = layer_find_by_name(data->value, dia);
445 /*printf( "layer: %s ", data->value );*/
446 break;
447 case 10:
448 if( points != 0 )
450 p[points-1].x = atof(data->value) * coord_scale * measure_scale;
451 /*printf( "P[%d].x: %f ", points-1, p[points-1].x );*/
453 break;
454 case 20:
455 if( points != 0 )
457 p[points-1].y = (-1)*atof(data->value) * coord_scale * measure_scale;
458 /*printf( "P[%d].y: %f\n", points-1, p[points-1].y );*/
460 break;
461 case 39:
462 line_width = atof(data->value) * WIDTH_SCALE;
463 /*printf( "width %f\n", line_width );*/
464 break;
465 case 42:
466 /* FIXME - the bulge code doesn't work */
467 p = realloc( p, sizeof( Point ) * ( points + 10 ));
469 start = p[points-2];
470 end = p[points-1];
472 radius = sqrt( pow( end.x - start.x, 2 ) + pow( end.y - start.y, 2 ))/2;
474 center.x = start.x + ( end.x - start.x )/2;
475 center.y = start.y + ( end.y - start.y )/2;
477 if( is_equal( start.x, end.x ))
479 if( is_equal( start.y, end.y ))
481 g_warning(_("Bad vertex bulge\n") );
483 else if( start.y > center.y )
485 /*start_angle = 90.0;*/
486 start_angle = M_PI/2;
488 else
490 /*start_angle = 270.0;*/
491 start_angle = M_PI * 1.5;
494 else if( is_equal( start.y, end.y ))
496 if( is_equal( start.x, end.x ))
498 g_warning( _("Bad vertex bulge\n") );
500 else if( start.x > center.x )
502 start_angle = 0.0;
504 else
506 start_angle = M_PI;
509 else
511 start_angle = atan( center.y - start.y /center.x - start.x );
514 /*printf( "start x %f end x %f center x %f\n", start.x, end.x, center.x );
515 printf( "start y %f end y %f center y %f\n", start.y, end.y, center.y );
516 printf( "bulge %s %f startx_angle %f\n", data->value, radius, start_angle );*/
518 for( i=(points-1); i<(points+9); i++ );
520 p[i].x = center.x + cos( start_angle ) * radius;
521 p[i].y = center.y + sin( start_angle ) * radius;
522 start_angle += M_PI/10.0;
523 /*printf( "i %d x %f y %f\n", i, p[i].x, p[i].y );*/
525 points += 10;
527 p[points-1] = end;
528 break;
529 case 62:
530 colour = atoi(data->value);
531 line_colour.red = acad_pal[colour].r / 255.0;
532 line_colour.green = acad_pal[colour].g / 255.0;
533 line_colour.blue = acad_pal[colour].b / 255.0;
534 break;
535 case 70:
536 closed = 1 & atoi( data->value );
537 /*printf( "closed %d %s", closed, data->value );*/
538 break;
540 } while( strcmp( data->value, "SEQEND" ));
542 setlocale(LC_NUMERIC, old_locale);
544 if( points == 0 )
546 printf( "No vertexes defined\n" );
547 return( NULL );
550 pcd = g_new( MultipointCreateData, 1);
552 if( closed )
554 ++points;
555 p = realloc( p, sizeof( Point ) * points );
556 p[points-1].x = p[0].x;
557 p[points-1].y = p[0].y;
560 pcd->num_points = points;
561 pcd->points = g_new( Point, pcd->num_points );
563 memcpy( pcd->points, p, sizeof( Point ) * pcd->num_points );
565 free( p );
567 polyline_obj = otype->ops->create( NULL, pcd, &h1, &h2 );
569 layer_add_object( layer, polyline_obj );
571 props = prop_list_from_descs( dxf_polyline_prop_descs, pdtpp_true );
572 g_assert( props->len == 3 );
574 cprop = g_ptr_array_index( props,0 );
575 cprop->color_data = line_colour;
577 rprop = g_ptr_array_index( props,1 );
578 rprop->real_data = line_width;
580 lsprop = g_ptr_array_index( props,2 );
581 lsprop->style = style;
582 lsprop->dash = 1.0;
584 polyline_obj->ops->set_props( polyline_obj, props );
586 prop_list_free(props);
588 return( polyline_obj );
591 static PropDescription dxf_ellipse_prop_descs[] = {
592 { "elem_corner", PROP_TYPE_POINT },
593 { "elem_width", PROP_TYPE_REAL },
594 { "elem_height", PROP_TYPE_REAL },
595 { "line_colour", PROP_TYPE_COLOUR },
596 { "line_width", PROP_TYPE_REAL },
597 { "show_background", PROP_TYPE_BOOL},
598 PROP_DESC_END};
600 /* reads a circle entity from the dxf file and creates a circle object in dia*/
601 DiaObject *read_entity_circle_dxf(FILE *filedxf, DxfData *data, DiagramData *dia)
603 int codedxf;
604 char *old_locale;
606 /* circle data */
607 Point center;
608 real radius = 1.0;
610 DiaObjectType *otype = object_get_type("Standard - Ellipse");
611 Handle *h1, *h2;
613 DiaObject *ellipse_obj;
614 Color line_colour = { 0.0, 0.0, 0.0 };
616 PointProperty *ptprop;
617 RealProperty *rprop;
618 BoolProperty *bprop;
619 ColorProperty *cprop;
620 GPtrArray *props;
622 real line_width = DEFAULT_LINE_WIDTH;
623 Layer *layer = NULL;
625 old_locale = setlocale(LC_NUMERIC, "C");
626 do {
627 if(read_dxf_codes(filedxf, data) == FALSE){
628 setlocale(LC_NUMERIC, old_locale);
629 return( NULL );
631 codedxf = atoi(data->code);
632 switch(codedxf){
633 case 8:
634 layer = layer_find_by_name(data->value, dia);
635 break;
636 case 10:
637 center.x = atof(data->value) * coord_scale * measure_scale;
638 break;
639 case 20:
640 center.y = (-1)*atof(data->value) * coord_scale * measure_scale;
641 break;
642 case 39:
643 line_width = atof(data->value) * WIDTH_SCALE;
644 break;
645 case 40:
646 radius = atof(data->value) * coord_scale * measure_scale;
647 break;
650 } while(codedxf != 0);
651 setlocale(LC_NUMERIC, old_locale);
653 center.x -= radius;
654 center.y -= radius;
655 ellipse_obj = otype->ops->create(&center, otype->default_user_data,
656 &h1, &h2);
657 layer_add_object(layer, ellipse_obj);
659 props = prop_list_from_descs(dxf_ellipse_prop_descs,pdtpp_true);
660 g_assert(props->len == 6);
662 ptprop = g_ptr_array_index(props,0);
663 ptprop->point_data = center;
664 rprop = g_ptr_array_index(props,1);
665 rprop->real_data = radius * 2.0;
666 rprop = g_ptr_array_index(props,2);
667 rprop->real_data = radius * 2.0;
668 cprop = g_ptr_array_index(props,3);
669 cprop->color_data = line_colour;
670 rprop = g_ptr_array_index(props,4);
671 rprop->real_data = line_width;
672 bprop = g_ptr_array_index(props,5);
673 bprop->bool_data = FALSE;
675 ellipse_obj->ops->set_props(ellipse_obj, props);
676 prop_list_free(props);
678 return( ellipse_obj );
681 static PropDescription dxf_arc_prop_descs[] = {
682 { "start_point", PROP_TYPE_POINT },
683 { "end_point", PROP_TYPE_POINT },
684 { "curve_distance", PROP_TYPE_REAL },
685 { "line_colour", PROP_TYPE_COLOUR },
686 { "line_width", PROP_TYPE_REAL },
687 PROP_DESC_END};
689 /* reads a circle entity from the dxf file and creates a circle object in dia*/
690 DiaObject *read_entity_arc_dxf(FILE *filedxf, DxfData *data, DiagramData *dia)
692 int codedxf;
693 char *old_locale;
695 /* arc data */
696 Point start,center,end;
697 real radius = 1.0, start_angle = 0.0, end_angle=360.0;
698 real curve_distance;
700 DiaObjectType *otype = object_get_type("Standard - Arc");
701 Handle *h1, *h2;
703 DiaObject *arc_obj;
704 Color line_colour = { 0.0, 0.0, 0.0 };
706 ColorProperty *cprop;
707 PointProperty *ptprop;
708 RealProperty *rprop;
709 GPtrArray *props;
711 real line_width = DEFAULT_LINE_WIDTH;
712 Layer *layer = NULL;
714 old_locale = setlocale(LC_NUMERIC, "C");
715 do {
716 if(read_dxf_codes(filedxf, data) == FALSE){
717 setlocale(LC_NUMERIC,old_locale);
718 return( NULL );
720 codedxf = atoi(data->code);
721 switch(codedxf){
722 case 8:
723 layer = layer_find_by_name(data->value, dia);
724 break;
725 case 10:
726 center.x = atof(data->value) * coord_scale * measure_scale;
727 break;
728 case 20:
729 center.y = (-1)*atof(data->value) * coord_scale * measure_scale;
730 break;
731 case 39:
732 line_width = atof(data->value) * WIDTH_SCALE;
733 break;
734 case 40:
735 radius = atof(data->value) * coord_scale * measure_scale;
736 break;
737 case 50:
738 start_angle = atof(data->value)*M_PI/180.0;
739 break;
740 case 51:
741 end_angle = atof(data->value)*M_PI/180.0;
742 break;
744 } while(codedxf != 0);
745 setlocale(LC_NUMERIC, old_locale);
747 /* printf("c.x=%f c.y=%f s",center.x,center.y); */
748 start.x = center.x + cos(start_angle) * radius;
749 start.y = center.y - sin(start_angle) * radius;
750 end.x = center.x + cos(end_angle) * radius;
751 end.y = center.y - sin(end_angle) * radius;
752 /*printf("s.x=%f s.y=%f e.x=%f e.y=%f\n",start.x,start.y,end.x,end.y);*/
755 if (end_angle < start_angle) end_angle += 2.0*M_PI;
756 curve_distance = radius * (1 - cos ((end_angle - start_angle)/2));
758 /*printf("start_angle: %f end_angle: %f radius:%f curve_distance:%f\n",
759 start_angle,end_angle,radius,curve_distance);*/
761 arc_obj = otype->ops->create(&center, otype->default_user_data,
762 &h1, &h2);
763 layer_add_object(layer, arc_obj);
765 props = prop_list_from_descs(dxf_arc_prop_descs,pdtpp_true);
766 g_assert(props->len == 5);
768 ptprop = g_ptr_array_index(props,0);
769 ptprop->point_data = start;
770 ptprop = g_ptr_array_index(props,1);
771 ptprop->point_data = end;
772 rprop = g_ptr_array_index(props,2);
773 rprop->real_data = curve_distance;
774 cprop = g_ptr_array_index(props,3);
775 cprop->color_data = line_colour;
776 rprop = g_ptr_array_index(props,4);
777 rprop->real_data = line_width;
779 arc_obj->ops->set_props(arc_obj, props);
780 prop_list_free(props);
782 return( arc_obj );
785 /* reads an ellipse entity from the dxf file and creates an ellipse object in dia*/
786 DiaObject *read_entity_ellipse_dxf(FILE *filedxf, DxfData *data, DiagramData *dia){
787 int codedxf;
788 char *old_locale;
790 /* ellipse data */
791 Point center;
792 real width = 1.0;
793 real ratio_width_height = 1.0;
795 DiaObjectType *otype = object_get_type("Standard - Ellipse");
796 Handle *h1, *h2;
798 DiaObject *ellipse_obj;
799 Color line_colour = { 0.0, 0.0, 0.0 };
800 PointProperty *ptprop;
801 RealProperty *rprop;
802 BoolProperty *bprop;
803 ColorProperty *cprop;
804 GPtrArray *props;
806 real line_width = DEFAULT_LINE_WIDTH;
807 Layer *layer = NULL;
809 old_locale = setlocale(LC_NUMERIC, "C");
810 do {
811 if(read_dxf_codes(filedxf, data) == FALSE){
812 setlocale(LC_NUMERIC, old_locale);
813 return( NULL );
815 codedxf = atoi(data->code);
816 switch(codedxf){
817 case 8:
818 layer = layer_find_by_name(data->value, dia);
819 break;
820 case 10:
821 center.x = atof(data->value) * coord_scale * measure_scale;
822 break;
823 case 11:
824 ratio_width_height = atof(data->value) * coord_scale * measure_scale;
825 break;
826 case 20:
827 center.y = (-1)*atof(data->value) * coord_scale * measure_scale;
828 break;
829 case 39:
830 line_width = atof(data->value) * WIDTH_SCALE;
831 break;
832 case 40:
833 width = atof(data->value) * 2; /* XXX what scale */
834 break;
836 } while(codedxf != 0);
837 setlocale(LC_NUMERIC, old_locale);
839 center.x -= width;
840 center.y -= (width*ratio_width_height);
841 ellipse_obj = otype->ops->create(&center, otype->default_user_data,
842 &h1, &h2);
843 layer_add_object(layer, ellipse_obj);
845 props = prop_list_from_descs(dxf_ellipse_prop_descs,pdtpp_true);
846 g_assert(props->len == 6);
848 ptprop = g_ptr_array_index(props,0);
849 ptprop->point_data = center;
850 rprop = g_ptr_array_index(props,1);
851 rprop->real_data = width;
852 rprop = g_ptr_array_index(props,2);
853 rprop->real_data = width * ratio_width_height;
854 cprop = g_ptr_array_index(props,3);
855 cprop->color_data = line_colour;
856 rprop = g_ptr_array_index(props,4);
857 rprop->real_data = line_width;
858 bprop = g_ptr_array_index(props,5);
859 bprop->bool_data = FALSE;
861 ellipse_obj->ops->set_props(ellipse_obj, props);
862 prop_list_free(props);
864 return( ellipse_obj );
867 static PropDescription dxf_text_prop_descs[] = {
868 { "text", PROP_TYPE_TEXT },
869 PROP_DESC_END};
871 DiaObject *read_entity_text_dxf(FILE *filedxf, DxfData *data, DiagramData *dia)
873 int codedxf, colour;
874 char *old_locale;
876 /* text data */
877 Point location;
878 real height = text_scale * coord_scale * measure_scale;
879 real y_offset = 0;
880 Alignment textalignment = ALIGN_LEFT;
881 char *textvalue = NULL, *textp;
883 DiaObjectType *otype = object_get_type("Standard - Text");
884 Handle *h1, *h2;
886 DiaObject *text_obj;
887 Color text_colour = { 0.0, 0.0, 0.0 };
889 TextProperty *tprop;
890 GPtrArray *props;
892 Layer *layer = NULL;
894 old_locale = setlocale(LC_NUMERIC, "C");
895 do {
896 if (read_dxf_codes(filedxf, data) == FALSE) {
897 setlocale(LC_NUMERIC,old_locale);
898 return( NULL );
900 codedxf = atoi(data->code);
901 switch (codedxf) {
902 case 1:
903 textvalue = g_strdup(data->value);
904 textp = textvalue;
905 /* FIXME - poor tab to space converter */
908 if( textp[0] == '^' && textp[1] == 'I' )
910 textp[0] = ' ';
911 textp[1] = ' ';
912 textp++;
916 while( *(++textp) != '\0' );
918 /*printf( "Found text: %s\n", textvalue );*/
919 break;
920 case 8: layer = layer_find_by_name(data->value, dia);
921 break;
922 case 10:
923 location.x = atof(data->value) * coord_scale * measure_scale;
924 /*printf( "Found text location x: %f\n", location.x );*/
925 break;
926 case 11:
927 location.x = atof(data->value) * coord_scale * measure_scale;
928 /*printf( "Found text location x: %f\n", location.x );*/
929 break;
930 case 20:
931 location.y = (-1)*atof(data->value) * coord_scale * measure_scale;
932 /*printf( "Found text location y: %f\n", location.y );*/
933 break;
934 case 21:
935 location.y = (-1)*atof(data->value) * coord_scale * measure_scale;
936 /*location.y = (-1)*atof(data->value) / text_scale;*/
937 printf( "Found text location y: %f\n", location.y );
938 break;
939 case 40:
940 height = atof(data->value) * coord_scale * measure_scale;
941 /*printf( "text height %f\n", height );*/
942 break;
943 case 62:
944 colour = atoi(data->value);
945 text_colour.red = acad_pal[colour].r / 255.0;
946 text_colour.green = acad_pal[colour].g / 255.0;
947 text_colour.blue = acad_pal[colour].b / 255.0;
948 break;
949 case 72:
950 switch(atoi(data->value))
952 case 0:
953 textalignment = ALIGN_LEFT;
954 break;
955 case 1:
956 textalignment = ALIGN_CENTER;
957 break;
958 case 2:
959 textalignment = ALIGN_RIGHT;
960 break;
961 case 3:
962 /* FIXME - it's not clear what these are */
963 break;
964 case 4:
965 /* FIXME - it's not clear what these are */
966 break;
967 case 5:
968 /* FIXME - it's not clear what these are */
969 break;
971 break;
972 case 73:
973 switch(atoi(data->value))
975 case 0:
976 case 1:
977 /* FIXME - not really the same vertical alignment */
978 /* 0 = baseline */
979 /* 1 = bottom */
980 y_offset = 0;
981 break;
982 case 2:
983 /* 2 = middle */
984 y_offset = 0.5;
985 break;
986 case 3:
987 /* 3 = top */
988 y_offset = 1;
989 break;
991 break;
993 } while(codedxf != 0);
994 setlocale(LC_NUMERIC,old_locale);
996 location.y += y_offset * height;
998 text_obj = otype->ops->create(&location, otype->default_user_data,
999 &h1, &h2);
1000 layer_add_object(layer, text_obj);
1001 props = prop_list_from_descs(dxf_text_prop_descs,pdtpp_true);
1002 g_assert(props->len == 1);
1004 tprop = g_ptr_array_index(props,0);
1005 g_free(tprop->text_data);
1006 tprop->text_data = textvalue;
1007 tprop->attr.alignment = textalignment;
1008 tprop->attr.position.x = location.x;
1009 tprop->attr.position.y = location.y;
1011 attributes_get_default_font(&tprop->attr.font, &tprop->attr.height);
1012 tprop->attr.color = text_colour;
1014 text_obj->ops->set_props(text_obj, props);
1015 prop_list_free(props);
1017 return( text_obj );
1020 /* reads the layer table from the dxf file and creates the layers */
1021 void read_table_layer_dxf(FILE *filedxf, DxfData *data, DiagramData *dia){
1022 int codedxf;
1024 do {
1025 if(read_dxf_codes(filedxf, data) == FALSE){
1026 return;
1028 else {
1029 codedxf = atoi(data->code);
1030 if(codedxf == 2){
1031 layer_find_by_name( data->value, dia );
1034 } while ((codedxf != 0) || (strcmp(data->value, "ENDTAB") != 0));
1037 /* reads a scale entity from the dxf file */
1038 void read_entity_scale_dxf(FILE *filedxf, DxfData *data, DiagramData *dia)
1040 int codedxf;
1042 if(read_dxf_codes(filedxf, data) == FALSE)
1043 return;
1045 codedxf = atoi(data->code);
1047 switch(codedxf)
1049 case 40:
1050 coord_scale = atof(data->value);
1051 g_message(_("Scale: %f\n"), coord_scale );
1052 break;
1054 default:
1055 break;
1060 /* reads a scale entity from the dxf file */
1061 void read_entity_measurement_dxf(FILE *filedxf, DxfData *data,
1062 DiagramData *dia)
1064 int codedxf;
1066 if(read_dxf_codes(filedxf, data) == FALSE)
1067 return;
1069 codedxf = atoi(data->code);
1071 switch(codedxf)
1073 case 70:
1074 /* value 0 = English, 1 = Metric */
1075 if( atoi( data->value ) == 0 )
1076 measure_scale = 2.54;
1077 else
1078 measure_scale = 1.0;
1079 /*printf( "Measure Scale: %f\n", measure_scale );*/
1080 break;
1082 default:
1083 break;
1088 /* reads a textsize entity from the dxf file */
1089 void read_entity_textsize_dxf(FILE *filedxf, DxfData *data, DiagramData *dia){
1090 int codedxf;
1092 if(read_dxf_codes(filedxf, data) == FALSE)
1093 return;
1095 codedxf = atoi(data->code);
1097 switch(codedxf)
1099 case 40:
1100 text_scale = atof(data->value);
1101 /*printf( "Text Size: %f\n", text_scale );*/
1102 break;
1103 default:
1104 break;
1109 /* reads the headers section of the dxf file */
1110 void read_section_header_dxf(FILE *filedxf, DxfData *data, DiagramData *dia) {
1111 int codedxf;
1113 if(read_dxf_codes(filedxf, data) == FALSE){
1114 return;
1116 do {
1117 codedxf = atoi(data->code);
1118 if((codedxf == 9) && (strcmp(data->value, "$DIMSCALE") == 0)) {
1119 read_entity_scale_dxf(filedxf, data, dia);
1120 } else if((codedxf == 9) && (strcmp(data->value, "$TEXTSIZE") == 0)) {
1121 read_entity_textsize_dxf(filedxf, data, dia);
1122 } else if((codedxf == 9) && (strcmp(data->value, "$MEASUREMENT") == 0)) {
1123 read_entity_measurement_dxf(filedxf, data, dia);
1124 } else {
1125 if(read_dxf_codes(filedxf, data) == FALSE){
1126 return;
1130 } while ((codedxf != 0) || (strcmp(data->value, "ENDSEC") != 0));
1133 /* reads the classes section of the dxf file */
1134 void read_section_classes_dxf(FILE *filedxf, DxfData *data, DiagramData *dia) {
1135 int codedxf;
1137 if(read_dxf_codes(filedxf, data) == FALSE){
1138 return;
1140 do {
1141 codedxf = atoi(data->code);
1142 if((codedxf == 9) && (strcmp(data->value, "$LTSCALE") == 0)) {
1143 read_entity_scale_dxf(filedxf, data, dia);
1144 } else if((codedxf == 9) && (strcmp(data->value, "$TEXTSIZE") == 0)) {
1145 read_entity_textsize_dxf(filedxf, data, dia);
1146 } else {
1147 if(read_dxf_codes(filedxf, data) == FALSE){
1148 return;
1152 } while ((codedxf != 0) || (strcmp(data->value, "ENDSEC") != 0));
1155 /* reads the tables section of the dxf file */
1156 void read_section_tables_dxf(FILE *filedxf, DxfData *data, DiagramData *dia) {
1157 int codedxf;
1159 if(read_dxf_codes(filedxf, data) == FALSE){
1160 return;
1162 do {
1163 codedxf = atoi(data->code);
1164 if((codedxf == 0) && (strcmp(data->value, "LAYER") == 0)) {
1165 read_table_layer_dxf(filedxf, data, dia);
1167 else {
1168 if(read_dxf_codes(filedxf, data) == FALSE){
1169 return;
1172 } while ((codedxf != 0) || (strcmp(data->value, "ENDSEC") != 0));
1175 /* reads the entities section of the dxf file */
1176 void read_section_entities_dxf(FILE *filedxf, DxfData *data, DiagramData *dia) {
1177 int codedxf;
1179 if (read_dxf_codes(filedxf, data) == FALSE){
1180 return;
1182 codedxf = atoi(data->code);
1183 do {
1184 if((codedxf == 0) && (strcmp(data->value, "LINE") == 0)) {
1185 read_entity_line_dxf(filedxf, data, dia);
1186 } else if((codedxf == 0) && (strcmp(data->value, "VERTEX") == 0)) {
1187 read_entity_line_dxf(filedxf, data, dia);
1188 } else if((codedxf == 0) && (strcmp(data->value, "SOLID") == 0)) {
1189 read_entity_solid_dxf(filedxf, data, dia);
1190 } else if((codedxf == 0) && (strcmp(data->value, "POLYLINE") == 0)) {
1191 read_entity_polyline_dxf(filedxf, data, dia);
1192 } else if((codedxf == 0) && (strcmp(data->value, "CIRCLE") == 0)) {
1193 read_entity_circle_dxf(filedxf, data, dia);
1194 } else if((codedxf == 0) && (strcmp(data->value, "ELLIPSE") == 0)) {
1195 read_entity_ellipse_dxf(filedxf, data, dia);
1196 } else if((codedxf == 0) && (strcmp(data->value, "TEXT") == 0)) {
1197 read_entity_text_dxf(filedxf, data, dia);
1198 } else if((codedxf == 0) && (strcmp(data->value, "ARC") == 0)) {
1199 read_entity_arc_dxf(filedxf,data,dia);
1200 } else {
1201 if(read_dxf_codes(filedxf, data) == FALSE) {
1202 return;
1205 codedxf = atoi(data->code);
1206 } while((codedxf != 0) || (strcmp(data->value, "ENDSEC") != 0));
1209 /* reads the blocks section of the dxf file */
1210 void read_section_blocks_dxf(FILE *filedxf, DxfData *data, DiagramData *dia)
1212 int codedxf, group_items = 0, group = 0;
1213 GList *group_list = NULL;
1214 DiaObject *obj = NULL;
1215 Layer *group_layer = NULL;
1217 if (read_dxf_codes(filedxf, data) == FALSE){
1218 return;
1220 codedxf = atoi(data->code);
1221 do {
1222 if((codedxf == 0) && (strcmp(data->value, "LINE") == 0)) {
1223 read_entity_line_dxf(filedxf, data, dia);
1224 } else if((codedxf == 0) && (strcmp(data->value, "SOLID") == 0)) {
1225 obj = read_entity_solid_dxf(filedxf, data, dia);
1226 } else if((codedxf == 0) && (strcmp(data->value, "VERTEX") == 0)) {
1227 read_entity_line_dxf(filedxf, data, dia);
1228 } else if((codedxf == 0) && (strcmp(data->value, "POLYLINE") == 0)) {
1229 obj = read_entity_polyline_dxf(filedxf, data, dia);
1230 } else if((codedxf == 0) && (strcmp(data->value, "CIRCLE") == 0)) {
1231 read_entity_circle_dxf(filedxf, data, dia);
1232 } else if((codedxf == 0) && (strcmp(data->value, "ELLIPSE") == 0)) {
1233 read_entity_ellipse_dxf(filedxf, data, dia);
1234 } else if((codedxf == 0) && (strcmp(data->value, "TEXT") == 0)) {
1235 obj = read_entity_text_dxf(filedxf, data, dia);
1236 } else if((codedxf == 0) && (strcmp(data->value, "ARC") == 0)) {
1237 read_entity_arc_dxf(filedxf,data,dia);
1238 } else if((codedxf == 0) && (strcmp(data->value, "BLOCK") == 0)) {
1239 /* printf("Begin group\n" ); */
1241 group = TRUE;
1242 group_items = 0;
1243 group_list = NULL;
1244 group_layer = NULL;
1246 do {
1247 if(read_dxf_codes(filedxf, data) == FALSE)
1248 return;
1250 codedxf = atoi(data->code);
1252 if( codedxf == 8 )
1253 group_layer = layer_find_by_name( data->value, dia );
1255 } while( codedxf != 0 );
1257 } else if((codedxf == 0) && (strcmp(data->value, "ENDBLK") == 0)) {
1258 /* printf( "End group %d\n", group_items ); */
1260 if( group && group_items > 0 && group_list != NULL )
1262 obj = group_create( group_list );
1263 if( NULL == group_layer )
1264 layer_add_object( dia->active_layer, obj );
1265 else
1266 layer_add_object( group_layer, obj );
1269 group = FALSE;
1270 group_items = 0;
1271 group_list = NULL;
1272 obj = NULL;
1274 if(read_dxf_codes(filedxf, data) == FALSE)
1275 return;
1277 } else {
1278 if(read_dxf_codes(filedxf, data) == FALSE) {
1279 return;
1283 if( group && obj != NULL )
1285 group_items++;
1287 group_list = g_list_prepend( group_list, obj );
1289 obj = NULL;
1292 codedxf = atoi(data->code);
1293 } while((codedxf != 0) || (strcmp(data->value, "ENDSEC") != 0));
1296 /* imports the given dxf-file, returns TRUE if successful */
1297 gboolean
1298 import_dxf(const gchar *filename, DiagramData *dia, void* user_data)
1300 FILE *filedxf;
1301 DxfData *data;
1302 int codedxf;
1304 filedxf = fopen(filename,"r");
1305 if(filedxf == NULL){
1306 message_error(_("Couldn't open: '%s' for reading.\n"),
1307 dia_message_filename(filename));
1308 return FALSE;
1311 data = g_new(DxfData, 1);
1313 do {
1314 if(read_dxf_codes(filedxf, data) == FALSE) {
1315 g_free(data);
1316 message_error(_("read_dxf_codes failed on '%s'\n"),
1317 dia_message_filename(filename) );
1318 return FALSE;
1320 else {
1321 codedxf = atoi(data->code);
1322 if(codedxf == 2) {
1323 if(strcmp(data->value, "ENTITIES") == 0) {
1324 /*printf( "reading section entities\n" );*/
1325 read_section_entities_dxf(filedxf, data, dia);
1327 else if(strcmp(data->value, "BLOCKS") == 0) {
1328 /*printf( "reading section BLOCKS\n" );*/
1329 read_section_blocks_dxf(filedxf, data, dia);
1331 else if(strcmp(data->value, "CLASSES") == 0) {
1332 /*printf( "reading section CLASSES\n" );*/
1333 read_section_classes_dxf(filedxf, data, dia);
1335 else if(strcmp(data->value, "HEADER") == 0) {
1336 /*printf( "reading section HEADER\n" );*/
1337 read_section_header_dxf(filedxf, data, dia);
1339 else if(strcmp(data->value, "TABLES") == 0) {
1340 /*printf( "reading section tables\n" );*/
1341 read_section_tables_dxf(filedxf, data, dia);
1343 else if(strcmp(data->value, "OBJECTS") == 0) {
1344 /*printf( "reading section objects\n" );*/
1345 read_section_entities_dxf(filedxf, data, dia);
1348 else
1349 g_warning(_("Unknown dxf code %d\n"), codedxf );
1351 }while((codedxf != 0) || (strcmp(data->value, "EOF") != 0));
1353 g_free(data);
1355 return TRUE;
1358 /* reads a code/value pair from the DXF file */
1359 gboolean read_dxf_codes(FILE *filedxf, DxfData *data){
1360 int i;
1361 char *c;
1363 if(fgets(data->code, DXF_LINE_LENGTH, filedxf) == NULL){
1364 return FALSE;
1366 if(fgets(data->value, DXF_LINE_LENGTH, filedxf) == NULL){
1367 return FALSE;
1369 c=data->value;
1370 for(i=0; i < DXF_LINE_LENGTH; i++){
1371 if((c[i] == '\n')||(c[i] == '\r')){
1372 c[i] = 0;
1373 break;
1376 return TRUE;
1379 /* interface from filter.h */
1381 static const gchar *extensions[] = {"dxf", NULL };
1382 DiaImportFilter dxf_import_filter = {
1383 N_("Drawing Interchange File"),
1384 extensions,
1385 import_dxf