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
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 #include "properties.h"
41 #include "propinternals.h"
43 static real coord_scale
= 5.0;
44 static real width_scale
= 10.0;
46 /* maximum line length */
47 #define DXF_LINE_LENGTH 256
49 typedef struct _DxfData
51 char code
[DXF_LINE_LENGTH
];
52 char value
[DXF_LINE_LENGTH
];
55 gboolean
import_dxf(const gchar
*filename
, DiagramData
*dia
, void* user_data
);
56 gboolean
read_dxf_codes(FILE *filedxf
, DxfData
*data
);
57 void read_entity_line_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
58 void read_entity_circle_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
59 void read_entity_ellipse_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
60 void read_entity_arc_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
61 void read_entity_text_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
62 void read_table_layer_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
63 void read_section_tables_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
64 void read_section_entities_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
);
65 Layer
*layer_find_by_name(char *layername
, DiagramData
*dia
);
66 LineStyle
get_dia_linestyle_dxf(char *dxflinestyle
);
68 /* returns the layer with the given name */
69 /* TODO: merge this with other layer code? */
70 Layer
*layer_find_by_name(char *layername
, DiagramData
*dia
) {
71 Layer
*matching_layer
, *layer
;
74 matching_layer
= dia
->active_layer
;
75 for (i
=0; i
<dia
->layers
->len
; i
++) {
76 layer
= (Layer
*)g_ptr_array_index(dia
->layers
, i
);
77 if(strcmp(layer
->name
, layername
) == 0) {
78 matching_layer
= layer
;
82 return matching_layer
;
85 /* returns the matching dia linestyle for a given dxf linestyle */
86 /* if no matching style is found, LINESTYLE solid is returned as a default */
87 LineStyle
get_dia_linestyle_dxf(char *dxflinestyle
) {
88 if(strcmp(dxflinestyle
, "DASH") == 0) {
89 return LINESTYLE_DASHED
;
91 if(strcmp(dxflinestyle
, "DASHDOT") == 0){
92 return LINESTYLE_DASH_DOT
;
94 if(strcmp(dxflinestyle
, "DOT") == 0){
95 return LINESTYLE_DOTTED
;
97 return LINESTYLE_SOLID
;
100 static PropDescription dxf_prop_descs
[] = {
101 { "start_point", PROP_TYPE_POINT
},
102 { "end_point", PROP_TYPE_POINT
},
103 { "line_colour", PROP_TYPE_COLOUR
},
104 { "line_width", PROP_TYPE_REAL
},
105 { "line_style", PROP_TYPE_LINESTYLE
},
108 /* reads a line entity from the dxf file and creates a line object in dia*/
109 void read_entity_line_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
){
116 ObjectType
*otype
= object_get_type("Standard - Line");
120 Color line_colour
= { 0.0, 0.0, 0.0 };
122 PointProperty
*ptprop
;
123 LinestyleProperty
*lsprop
;
124 ColorProperty
*cprop
;
127 real line_width
= 0.1;
128 LineStyle style
= LINESTYLE_SOLID
;
131 old_locale
= setlocale(LC_NUMERIC
, "C");
133 if(read_dxf_codes(filedxf
, data
) == FALSE
){
134 setlocale(LC_NUMERIC
, old_locale
);
137 codedxf
= atoi(data
->code
);
139 case 6: style
= get_dia_linestyle_dxf(data
->value
);
141 case 8: layer
= layer_find_by_name(data
->value
, dia
);
144 start
.x
= atof(data
->value
) / coord_scale
;
147 end
.x
= atof(data
->value
) / coord_scale
;
150 start
.y
= (-1)*atof(data
->value
) / coord_scale
;
153 end
.y
= (-1)*atof(data
->value
) / coord_scale
;
156 line_width
= atof(data
->value
) / width_scale
;
159 } while(codedxf
!= 0);
160 setlocale(LC_NUMERIC
, old_locale
);
162 line_obj
= otype
->ops
->create(&start
, otype
->default_user_data
,
164 layer_add_object(layer
, line_obj
);
166 props
= prop_list_from_descs(dxf_prop_descs
,pdtpp_true
);
167 g_assert(props
->len
== 5);
169 ptprop
= g_ptr_array_index(props
,0);
170 ptprop
->point_data
= start
;
172 ptprop
= g_ptr_array_index(props
,1);
173 ptprop
->point_data
= end
;
175 cprop
= g_ptr_array_index(props
,2);
176 cprop
->color_data
= line_colour
;
178 rprop
= g_ptr_array_index(props
,3);
179 rprop
->real_data
= line_width
;
181 lsprop
= g_ptr_array_index(props
,4);
182 lsprop
->style
= style
;
185 line_obj
->ops
->set_props(line_obj
, props
);
187 prop_list_free(props
);
190 static PropDescription dxf_ellipse_prop_descs
[] = {
191 { "elem_corner", PROP_TYPE_POINT
},
192 { "elem_width", PROP_TYPE_REAL
},
193 { "elem_height", PROP_TYPE_REAL
},
194 { "line_colour", PROP_TYPE_COLOUR
},
195 { "line_width", PROP_TYPE_REAL
},
196 { "show_background", PROP_TYPE_BOOL
},
199 /* reads a circle entity from the dxf file and creates a circle object in dia*/
200 void read_entity_circle_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
){
208 ObjectType
*otype
= object_get_type("Standard - Ellipse");
212 Color line_colour
= { 0.0, 0.0, 0.0 };
214 PointProperty
*ptprop
;
217 ColorProperty
*cprop
;
220 real line_width
= 0.1;
223 old_locale
= setlocale(LC_NUMERIC
, "C");
225 if(read_dxf_codes(filedxf
, data
) == FALSE
){
226 setlocale(LC_NUMERIC
, old_locale
);
229 codedxf
= atoi(data
->code
);
232 layer
= layer_find_by_name(data
->value
, dia
);
235 center
.x
= atof(data
->value
) / coord_scale
;
238 center
.y
= (-1)*atof(data
->value
) / coord_scale
;
241 line_width
= atof(data
->value
) / width_scale
;
244 radius
= atof(data
->value
) / coord_scale
;
248 } while(codedxf
!= 0);
249 setlocale(LC_NUMERIC
, old_locale
);
253 ellipse_obj
= otype
->ops
->create(¢er
, otype
->default_user_data
,
255 layer_add_object(layer
, ellipse_obj
);
257 props
= prop_list_from_descs(dxf_ellipse_prop_descs
,pdtpp_true
);
258 g_assert(props
->len
== 6);
260 ptprop
= g_ptr_array_index(props
,0);
261 ptprop
->point_data
= center
;
262 rprop
= g_ptr_array_index(props
,1);
263 rprop
->real_data
= radius
* 2.0;
264 rprop
= g_ptr_array_index(props
,2);
265 rprop
->real_data
= radius
* 2.0;
266 cprop
= g_ptr_array_index(props
,3);
267 cprop
->color_data
= line_colour
;
268 rprop
= g_ptr_array_index(props
,4);
269 rprop
->real_data
= line_width
;
270 bprop
= g_ptr_array_index(props
,5);
271 bprop
->bool_data
= FALSE
;
273 ellipse_obj
->ops
->set_props(ellipse_obj
, props
);
274 prop_list_free(props
);
277 static PropDescription dxf_arc_prop_descs
[] = {
278 { "start_point", PROP_TYPE_POINT
},
279 { "end_point", PROP_TYPE_POINT
},
280 { "curve_distance", PROP_TYPE_REAL
},
281 { "line_colour", PROP_TYPE_COLOUR
},
282 { "line_width", PROP_TYPE_REAL
},
285 /* reads a circle entity from the dxf file and creates a circle object in dia*/
286 void read_entity_arc_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
){
291 Point start
,center
,end
;
292 real radius
= 1.0, start_angle
= 0.0, end_angle
=360.0;
295 ObjectType
*otype
= object_get_type("Standard - Arc");
299 Color line_colour
= { 0.0, 0.0, 0.0 };
301 ColorProperty
*cprop
;
302 PointProperty
*ptprop
;
306 real line_width
= 0.1;
309 old_locale
= setlocale(LC_NUMERIC
, "C");
311 if(read_dxf_codes(filedxf
, data
) == FALSE
){
312 setlocale(LC_NUMERIC
,old_locale
);
315 codedxf
= atoi(data
->code
);
318 layer
= layer_find_by_name(data
->value
, dia
);
321 center
.x
= atof(data
->value
) / coord_scale
;
324 center
.y
= (-1)*atof(data
->value
) / coord_scale
;
327 line_width
= atof(data
->value
) / width_scale
;
330 radius
= atof(data
->value
) / coord_scale
;
333 start_angle
= atof(data
->value
)*M_PI
/180.0;
336 end_angle
= atof(data
->value
)*M_PI
/180.0;
339 } while(codedxf
!= 0);
340 setlocale(LC_NUMERIC
, old_locale
);
342 /* printf("c.x=%f c.y=%f s",center.x,center.y); */
343 start
.x
= center
.x
+ cos(start_angle
) * radius
;
344 start
.y
= center
.y
- sin(start_angle
) * radius
;
345 end
.x
= center
.x
+ cos(end_angle
) * radius
;
346 end
.y
= center
.y
- sin(end_angle
) * radius
;
347 /*printf("s.x=%f s.y=%f e.x=%f e.y=%f\n",start.x,start.y,end.x,end.y);*/
350 if (end_angle
< start_angle
) end_angle
+= 2.0*M_PI
;
351 curve_distance
= radius
* (1 - cos ((end_angle
- start_angle
)/2));
353 /*printf("start_angle: %f end_angle: %f radius:%f curve_distance:%f\n",
354 start_angle,end_angle,radius,curve_distance);*/
356 arc_obj
= otype
->ops
->create(¢er
, otype
->default_user_data
,
358 layer_add_object(layer
, arc_obj
);
360 props
= prop_list_from_descs(dxf_arc_prop_descs
,pdtpp_true
);
361 g_assert(props
->len
== 5);
363 ptprop
= g_ptr_array_index(props
,0);
364 ptprop
->point_data
= start
;
365 ptprop
= g_ptr_array_index(props
,1);
366 ptprop
->point_data
= end
;
367 rprop
= g_ptr_array_index(props
,2);
368 rprop
->real_data
= curve_distance
;
369 cprop
= g_ptr_array_index(props
,3);
370 cprop
->color_data
= line_colour
;
371 rprop
= g_ptr_array_index(props
,4);
372 rprop
->real_data
= line_width
;
374 arc_obj
->ops
->set_props(arc_obj
, props
);
375 prop_list_free(props
);
378 /* reads an ellipse entity from the dxf file and creates an ellipse object in dia*/
379 void read_entity_ellipse_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
){
386 real ratio_width_height
= 1.0;
388 ObjectType
*otype
= object_get_type("Standard - Ellipse");
392 Color line_colour
= { 0.0, 0.0, 0.0 };
393 PointProperty
*ptprop
;
396 ColorProperty
*cprop
;
399 real line_width
= 0.1;
402 old_locale
= setlocale(LC_NUMERIC
, "C");
404 if(read_dxf_codes(filedxf
, data
) == FALSE
){
405 setlocale(LC_NUMERIC
, old_locale
);
408 codedxf
= atoi(data
->code
);
411 layer
= layer_find_by_name(data
->value
, dia
);
414 center
.x
= atof(data
->value
) / coord_scale
;
417 ratio_width_height
= atof(data
->value
) / coord_scale
;
420 center
.y
= (-1)*atof(data
->value
) / coord_scale
;
423 line_width
= atof(data
->value
) / width_scale
;
426 width
= atof(data
->value
) * 2; /* XXX what scale */
429 } while(codedxf
!= 0);
430 setlocale(LC_NUMERIC
, old_locale
);
433 center
.y
-= (width
*ratio_width_height
);
434 ellipse_obj
= otype
->ops
->create(¢er
, otype
->default_user_data
,
436 layer_add_object(layer
, ellipse_obj
);
438 props
= prop_list_from_descs(dxf_ellipse_prop_descs
,pdtpp_true
);
439 g_assert(props
->len
== 6);
441 ptprop
= g_ptr_array_index(props
,0);
442 ptprop
->point_data
= center
;
443 rprop
= g_ptr_array_index(props
,1);
444 rprop
->real_data
= width
;
445 rprop
= g_ptr_array_index(props
,2);
446 rprop
->real_data
= width
* ratio_width_height
;
447 cprop
= g_ptr_array_index(props
,3);
448 cprop
->color_data
= line_colour
;
449 rprop
= g_ptr_array_index(props
,4);
450 rprop
->real_data
= line_width
;
451 bprop
= g_ptr_array_index(props
,5);
452 bprop
->bool_data
= FALSE
;
454 ellipse_obj
->ops
->set_props(ellipse_obj
, props
);
455 prop_list_free(props
);
458 static PropDescription dxf_text_prop_descs
[] = {
459 { "text", PROP_TYPE_TEXT
},
462 void read_entity_text_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
)
470 Alignment textalignment
= ALIGN_LEFT
;
471 char *textvalue
= NULL
;
473 ObjectType
*otype
= object_get_type("Standard - Text");
477 Color text_colour
= { 0.0, 0.0, 0.0 };
484 old_locale
= setlocale(LC_NUMERIC
, "C");
486 if (read_dxf_codes(filedxf
, data
) == FALSE
) {
487 setlocale(LC_NUMERIC
,old_locale
);
490 codedxf
= atoi(data
->code
);
492 case 1: textvalue
= g_strdup(data
->value
);
494 case 8: layer
= layer_find_by_name(data
->value
, dia
);
497 location
.x
= atof(data
->value
) / coord_scale
;
500 location
.y
= (-1)*atof(data
->value
) / coord_scale
;
503 height
= atof(data
->value
) / coord_scale
;
506 switch(atoi(data
->value
)){
507 case 0: textalignment
= ALIGN_LEFT
;
509 case 1: textalignment
= ALIGN_CENTER
;
511 case 2: textalignment
= ALIGN_RIGHT
;
515 } while(codedxf
!= 0);
516 setlocale(LC_NUMERIC
,old_locale
);
518 text_obj
= otype
->ops
->create(&location
, otype
->default_user_data
,
520 layer_add_object(layer
, text_obj
);
521 props
= prop_list_from_descs(dxf_text_prop_descs
,pdtpp_true
);
522 g_assert(props
->len
== 1);
524 tprop
= g_ptr_array_index(props
,0);
525 g_free(tprop
->text_data
);
526 tprop
->text_data
= textvalue
;
527 tprop
->attr
.alignment
= textalignment
;
528 tprop
->attr
.position
.x
= location
.x
;
529 tprop
->attr
.position
.y
= location
.y
;
530 tprop
->attr
.font
= font_getfont(_("Courier"));
531 tprop
->attr
.height
= height
;
533 text_obj
->ops
->set_props(text_obj
, props
);
534 prop_list_free(props
);
537 /* reads the layer table from the dxf file and creates the layers */
538 void read_table_layer_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
){
543 if(read_dxf_codes(filedxf
, data
) == FALSE
){
547 codedxf
= atoi(data
->code
);
549 layer
= new_layer(g_strdup(data
->value
));
550 data_add_layer(dia
, layer
);
553 } while ((codedxf
!= 0) || (strcmp(data
->value
, "ENDTAB") != 0));
556 /* reads the tables section of the dxf file */
557 void read_section_tables_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
) {
560 if(read_dxf_codes(filedxf
, data
) == FALSE
){
564 codedxf
= atoi(data
->code
);
565 if((codedxf
== 0) && (strcmp(data
->value
, "LAYER") == 0)) {
566 read_table_layer_dxf(filedxf
, data
, dia
);
569 if(read_dxf_codes(filedxf
, data
) == FALSE
){
573 } while ((codedxf
!= 0) || (strcmp(data
->value
, "ENDSEC") != 0));
576 /* reads the entities section of the dxf file */
577 void read_section_entities_dxf(FILE *filedxf
, DxfData
*data
, DiagramData
*dia
) {
580 if (read_dxf_codes(filedxf
, data
) == FALSE
){
583 codedxf
= atoi(data
->code
);
585 if((codedxf
== 0) && (strcmp(data
->value
, "LINE") == 0)) {
586 read_entity_line_dxf(filedxf
, data
, dia
);
587 } else if((codedxf
== 0) && (strcmp(data
->value
, "CIRCLE") == 0)) {
588 read_entity_circle_dxf(filedxf
, data
, dia
);
589 } else if((codedxf
== 0) && (strcmp(data
->value
, "ELLIPSE") == 0)) {
590 read_entity_ellipse_dxf(filedxf
, data
, dia
);
591 } else if((codedxf
== 0) && (strcmp(data
->value
, "TEXT") == 0)) {
592 read_entity_text_dxf(filedxf
, data
, dia
);
593 } else if((codedxf
== 0) && (strcmp(data
->value
, "ARC") == 0)) {
594 read_entity_arc_dxf(filedxf
,data
,dia
);
596 /* if (codedxf == 0) {
597 g_warning("unknown DXF entity: %s",data->value);
599 if(read_dxf_codes(filedxf
, data
) == FALSE
) {
603 codedxf
= atoi(data
->code
);
604 } while((codedxf
!= 0) || (strcmp(data
->value
, "ENDSEC") != 0));
607 /* imports the given dxf-file, returns TRUE if successful */
608 gboolean
import_dxf(const gchar
*filename
, DiagramData
*dia
, void* user_data
){
613 filedxf
= fopen(filename
,"r");
615 message_error(_("Couldn't open: '%s' for reading.\n"), filename
);
619 data
= g_new(DxfData
, 1);
622 if(read_dxf_codes(filedxf
, data
) == FALSE
) {
627 codedxf
= atoi(data
->code
);
629 if(strcmp(data
->value
, "ENTITIES") == 0) {
630 read_section_entities_dxf(filedxf
, data
, dia
);
632 else if(strcmp(data
->value
, "TABLES") == 0) {
633 read_section_tables_dxf(filedxf
, data
, dia
);
637 }while((codedxf
!= 0) || (strcmp(data
->value
, "EOF") != 0));
644 /* reads a code/value pair from the DXF file */
645 gboolean
read_dxf_codes(FILE *filedxf
, DxfData
*data
){
649 if(fgets(data
->code
, DXF_LINE_LENGTH
, filedxf
) == NULL
){
652 if(fgets(data
->value
, DXF_LINE_LENGTH
, filedxf
) == NULL
){
656 for(i
=0; i
< DXF_LINE_LENGTH
; i
++){
657 if((c
[i
] == '\n')||(c
[i
] == '\r')){
665 /* interface from filter.h */
667 static const gchar
*extensions
[] = {"dxf", NULL
};
668 DiaImportFilter dxf_import_filter
= {
669 N_("Drawing Interchange File"),