1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2018-2021 Free Software Foundation, Inc. */
5 /* */
6 /* This library is free software, licensed under the terms of the GNU */
7 /* General Public License as published by the Free Software Foundation, */
8 /* either version 3 of the License, or (at your option) any later version. */
9 /* You should have received a copy of the GNU General Public License */
10 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
11 /*****************************************************************************/
12
13 /*
14 * out_dxfb.c: write as Binary DXF
15 * Does not work yet.
16 * written by Reini Urban
17 */
18
19 #include "config.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <assert.h>
24
25 #define IS_DXF
26 #include "common.h"
27 #include "bits.h"
28 #include "dwg.h"
29 #include "decode.h"
30 #include "decode_r11.h"
31 #include "out_dxf.h"
32
33 static unsigned int loglevel;
34 #define DWG_LOGLEVEL loglevel
35 #include "logging.h"
36
37 /* the current version per spec block. */
38 static unsigned int cur_ver = 0;
39 static char buf[4096];
40 static BITCODE_BL rcount1, rcount2;
41
42 // imported
43 char *dwg_obj_table_get_name (const Dwg_Object *restrict obj,
44 int *restrict error);
45 #ifndef _DWG_API_H_
46 Dwg_Object *dwg_obj_generic_to_object (const void *restrict obj,
47 int *restrict error);
48 #endif
49
50 // private
51 static int dxfb_common_entity_handle_data (Bit_Chain *restrict dat,
52 const Dwg_Object *restrict obj);
53 static int dwg_dxfb_object (Bit_Chain *restrict dat,
54 const Dwg_Object *restrict obj, int *restrict);
55 static int dxfb_3dsolid (Bit_Chain *restrict dat,
56 const Dwg_Object *restrict obj,
57 Dwg_Entity_3DSOLID *restrict _obj);
58 /*static void dxfb_cvt_tablerecord (Bit_Chain *restrict dat,
59 const Dwg_Object *restrict obj,
60 char *restrict name, const int dxf); */
61
62 /*--------------------------------------------------------------------------------
63 * MACROS
64 */
65
66 #define ACTION dxfb
67
68 #define FMT_H "%" PRIX64
69 #define FIELD(nam, type)
70 #define FIELDG(nam, type, dxf) \
71 if (dxf) \
72 { \
73 FIELD_##type (nam, dxf); \
74 }
75 #define SUB_FIELD(o, nam, type, dxf) FIELDG (o.nam, type, dxf)
76
77 #define HEADER_VALUE(nam, type, dxf, value) \
78 if (dxf) \
79 { \
80 GROUP (9); \
81 fprintf (dat->fh, "$%s%c", #nam, 0); \
82 VALUE_##type (value, dxf); \
83 }
84
85 #define HEADER_VAR(nam, type, dxf) \
86 HEADER_VALUE (nam, type, dxf, dwg->header_vars.nam)
87 #define HEADER_VALUE_TV(nam, dxf, value) HEADER_VALUE (nam, TV, dxf, value)
88 #define HEADER_VALUE_TU(nam, dxf, value) HEADER_VALUE (nam, TU, dxf, value)
89 #define HEADER_VALUE_TU0(nam, dxf, value) \
90 if (dxf && value && !bit_empty_T (dat, (BITCODE_T)value)) \
91 { \
92 HEADER_VALUE (nam, TU, dxf, value); \
93 }
94
95 #define FIELD_CAST(nam, type, cast, dxf) FIELDG (nam, cast, dxf)
96 #define SUB_FIELD_CAST(o, nam, type, cast, dxf) FIELDG (o.nam, cast, dxf)
97 #define FIELD_TRACE(nam, type)
98 #define VALUE_TV(value, dxf) \
99 { \
100 GROUP (dxf); \
101 fprintf (dat->fh, "%s%c", value, 0); \
102 }
103 #define VALUE_TV0(value, dxf) \
104 if (dxf && value && *value) \
105 { \
106 GROUP (dxf); \
107 fprintf (dat->fh, "%s%c", value, 0); \
108 }
109 #define VALUE_TU(wstr, dxf) \
110 { \
111 if (dxf) \
112 { \
113 char *_u8 = bit_convert_TU ((BITCODE_TU)wstr); \
114 GROUP (dxf); \
115 if (_u8) \
116 fprintf (dat->fh, "%s%c", _u8, 0); \
117 else \
118 fprintf (dat->fh, "%c", 0); \
119 free (_u8); \
120 } \
121 }
122 #define VALUE_TFF(str, dxf) VALUE_TV (str, dxf)
123 #define VALUE_BINARY(value, size, dxf) \
124 { \
125 long _len = (long)(size); \
126 do \
127 { \
128 short j; \
129 long _l = _len > 127 ? 127 : _len; \
130 GROUP (dxf); \
131 if (value) \
132 for (j = 0; j < _l; j++) \
133 { \
134 fprintf (dat->fh, "%c", value[j]); \
135 } \
136 fprintf (dat->fh, "%c", '\0'); \
137 _len -= 127; \
138 } \
139 while (_len > 127); \
140 }
141 #define FIELD_BINARY(name, size, dxf) VALUE_BINARY (_obj->name, size, dxf)
142
143 #define FIELD_VALUE(nam) _obj->nam
144 #define ANYCODE -1
145 // a null-terminated string of the value as %X
146 #define VALUE_HANDLE(ref, nam, handle_code, dxf) \
147 if (dxf) \
148 { \
149 char _s[18]; \
150 snprintf (_s, sizeof (_s), FMT_H, ref ? ref->absolute_ref : 0UL); \
151 _s[sizeof (_s) - 1] = '\0'; \
152 VALUE_TV (_s, dxf); \
153 }
154 // TODO: try to resolve the handle. rather write 0 than in invalid handle:
155 // if (_obj->nam->obj) ...
156 #define FIELD_HANDLE(nam, handle_code, dxf) \
157 VALUE_HANDLE (_obj->nam, nam, handle_code, dxf)
158 #define FIELD_HANDLE0(nam, handle_code, dxf) \
159 if (dxf && _obj->nam && _obj->nam->absolute_ref) \
160 { \
161 FIELD_HANDLE (nam, handle_code, dxf); \
162 }
163 #define SUB_FIELD_HANDLE(o, nam, handle_code, dxf) \
164 VALUE_HANDLE (_obj->o.nam, nam, handle_code, dxf)
165 #define SUB_FIELD_HANDLE0(o, nam, handle_code, dxf) \
166 if (dxf && _obj->o.nam && _obj->o.nam->absolute_ref) \
167 { \
168 VALUE_HANDLE (_obj->o.nam, nam, handle_code, dxf) \
169 }
170
171 #define GROUP(code) \
172 if (dat->version < R_14) \
173 { \
174 if (code >= 1000) \
175 { \
176 uint16_t icode = (uint16_t)(code); \
177 fputc (0xff, dat->fh); \
178 fwrite (&icode, 2, 1, dat->fh); \
179 } \
180 else \
181 { \
182 uint8_t icode = (uint8_t)((code)&0xff); \
183 fwrite (&icode, 1, 1, dat->fh); \
184 } \
185 } \
186 else \
187 { \
188 uint16_t icode = (uint16_t)(code); \
189 fwrite (&icode, 2, 1, dat->fh); \
190 }
191 #define FIELD_TV(nam, dxf) \
192 if (_obj->nam != NULL && dxf != 0) \
193 { \
194 VALUE_TV (_obj->nam, dxf) \
195 }
196 #define FIELD_TU(nam, dxf) \
197 if (_obj->nam != NULL && dxf != 0) \
198 { \
199 VALUE_TU (_obj->nam, dxf) \
200 }
201 #define VALUE_T(value, dxf) \
202 { \
203 if (IS_FROM_TU (dat)) \
204 { \
205 VALUE_TU (value, dxf) \
206 } \
207 else \
208 { \
209 VALUE_TV ((char *)value, dxf) \
210 } \
211 }
212 #define VALUE_T0(value, dxf) \
213 if (!bit_empty_T (dat, value)) \
214 VALUE_T (value, dxf)
215 #define FIELD_T(nam, dxf) \
216 { \
217 if (IS_FROM_TU (dat)) \
218 { \
219 FIELD_TU (nam, dxf) \
220 } \
221 else \
222 { \
223 FIELD_TV (nam, dxf) \
224 } \
225 }
226 #define FIELD_TF(nam, len, dxf) VALUE_TV (_obj->nam, dxf)
227 #define FIELD_TFF(nam, len, dxf) VALUE_TV (_obj->nam, dxf)
228
229 // skip if 0
230 #define FIELD_RD0(nam, dxf) FIELD_BD0 (nam, dxf)
231 #define FIELD_BD0(nam, dxf) \
232 { \
233 if (_obj->nam != 0.0) \
234 FIELD_BD (nam, dxf) \
235 }
236 // for scale (1.0, 1.0, 1.0) and width_factor
237 #define FIELD_RD1(nam, dxf) FIELD_BD1 (nam, dxf)
238 #define FIELD_BD1(nam, dxf) \
239 { \
240 if (_obj->nam != 1.0) \
241 FIELD_BD (nam, dxf) \
242 }
243 #define FIELD_BL0(nam, dxf) \
244 { \
245 if (_obj->nam != 0) \
246 FIELD_BL (nam, dxf) \
247 }
248 #define SUB_FIELD_BL0(o, nam, dxf) \
249 { \
250 if (_obj->o.nam != 0) \
251 SUB_FIELD_BL (o, nam, dxf) \
252 }
253 #define FIELD_BS0(nam, dxf) \
254 { \
255 if (_obj->nam != 0) \
256 FIELD_BS (nam, dxf) \
257 }
258 #define FIELD_BS1(nam, dxf) \
259 { \
260 if (_obj->nam != 1) \
261 FIELD_BS (nam, dxf) \
262 }
263 #define FIELD_B0(nam, dxf) \
264 { \
265 if (_obj->nam) \
266 FIELD_B (nam, dxf) \
267 }
268 #define FIELD_RC0(nam, dxf) \
269 { \
270 if (_obj->nam != 0) \
271 FIELD_RC (nam, dxf) \
272 }
273 #define FIELD_RS0(nam, dxf) \
274 { \
275 if (_obj->nam != 0) \
276 FIELD_RS (nam, dxf) \
277 }
278 #define FIELD_RL0(nam, dxf) \
279 { \
280 if (_obj->nam != 0) \
281 FIELD_RL (nam, dxf) \
282 }
283 #define FIELD_BT0(nam, dxf) \
284 { \
285 if (_obj->nam != 0) \
286 FIELD_BT (nam, dxf) \
287 }
288 #define FIELD_T0(nam, dxf) \
289 if (!bit_empty_T (dat, _obj->nam)) \
290 { \
291 FIELD_T (nam, dxf) \
292 }
293 #define FIELD_TV0(nam, dxf) VALUE_TV0 (_obj->nam, dxf)
294
295 #define HEADER_TV(nam, dxf) \
296 { \
297 HEADER_9 (nam); \
298 VALUE_TV (dwg->header_vars.nam, dxf); \
299 }
300 #define HEADER_TU(nam, dxf) \
301 { \
302 HEADER_9 (nam); \
303 VALUE_TU (dwg->header_vars.nam, dxf); \
304 }
305 #define HEADER_T(nam, dxf) \
306 { \
307 HEADER_9 (nam); \
308 VALUE_T (dwg->header_vars.nam, dxf); \
309 }
310 #define HEADER_T0(nam, dxf) \
311 if (dxf && !bit_empty_T (dat, _obj->nam)) \
312 { \
313 HEADER_9 (nam); \
314 VALUE_T (_obj->nam, dxf); \
315 }
316 #define HEADER_VALUE_T(nam, dxf, value) \
317 if (dxf) \
318 { \
319 HEADER_9 (nam); \
320 if (IS_FROM_TU (dat)) \
321 VALUE_T (value, dxf) \
322 else \
323 VALUE_TV ((char *)value, dxf) \
324 }
325 #define HEADER_VALUE_T0(nam, dxf, value) \
326 if (dxf && !bit_empty_T (dat, value)) \
327 { \
328 HEADER_9 (nam); \
329 if (IS_FROM_TU (dat)) \
330 VALUE_T (value, dxf) \
331 else \
332 VALUE_TV ((char *)value, dxf) \
333 }
334 #define POINT_3D(nam, var, c1, c2, c3) \
335 { \
336 VALUE_RD (dwg->var.x, c1); \
337 VALUE_RD (dwg->var.y, c2); \
338 VALUE_RD (dwg->var.z, c3); \
339 }
340 #define POINT_2D(nam, var, c1, c2) \
341 { \
342 VALUE_RD (dwg->var.x, c1); \
343 VALUE_RD (dwg->var.x, c2); \
344 }
345 #define HEADER_3D(nam) \
346 { \
347 HEADER_9 (nam); \
348 POINT_3D (nam, header_vars.nam, 10, 20, 30); \
349 }
350 #define HEADER_2D(nam) \
351 { \
352 HEADER_9 (nam); \
353 POINT_2D (nam, header_vars.nam, 10, 20); \
354 }
355 #define SECTION(token) \
356 VALUE_TV ("SECTION", 0); \
357 VALUE_TV (#token, 2)
358 #define ENDSEC() VALUE_TV ("ENDSEC", 0)
359 #define TABLE(token) \
360 VALUE_TV ("TABLE", 0); \
361 VALUE_TV (#token, 2)
362 #define ENDTAB() VALUE_TV ("ENDTAB", 0)
363 #define RECORD(token) VALUE_TV (#token, 0)
364 #define SUBCLASS(text) \
365 if (dat->version >= R_13b1) \
366 { \
367 VALUE_TV (#text, 100) \
368 }
369
370 /*
371 #define VALUE(code, value) \
372 { \
373 GCC30_DIAG_IGNORE (-Wformat-nonliteral) \
374 snprintf (buf, 4096, "%3i\n%s\n", code, dxfb_format (code)); \
375 fprintf(dat->fh, buf, value); \
376 GCC_DIAG_RESTORE \
377 }
378 */
379
380 #define FIELD_HANDLE_N(nam, vcount, handle_code, dxf) \
381 FIELD_HANDLE (nam, handle_code, dxf)
382
383 #define FIELD_B(nam, dxf) FIELD_RC (nam, dxf)
384 #define FIELD_BB(nam, dxf) FIELD_RC (nam, dxf)
385 #define FIELD_3B(nam, dxf) FIELD_RC (nam, dxf)
386 #define FIELD_BS(nam, dxf) FIELD_RS (nam, dxf)
387 #define FIELD_BL(nam, dxf) FIELD_RL (nam, dxf)
388 #define HEADER_BLL(nam, dxf) HEADER_RLL (nam, dxf)
389 #define FIELD_BD(nam, dxf) FIELD_RD (nam, dxf)
390
391 #define HEADER_9(nam) \
392 { \
393 GROUP (9); \
394 fprintf (dat->fh, "$%s%c", #nam, 0); \
395 }
396 #define VALUE(value, type, dxf) VALUE_##type (value, dxf)
397 #define VALUE_B(value, dxf) VALUE_INT (value, dxf)
398 #define VALUE_BB(value, dxf) VALUE_INT (value, dxf)
399 #define VALUE_3B(value, dxf) VALUE_INT (value, dxf)
400 #define VALUE_RCs(value, dxf) VALUE_INT (value, dxf)
401 #define VALUE_BS(value, dxf) VALUE_INT (value, dxf)
402 #define VALUE_BL(value, dxf) VALUE_INT (value, dxf)
403 #define VALUE_BD(value, dxf) VALUE_RD (value, dxf)
404 #define VALUE_RC(value, dxf) \
405 { \
406 BITCODE_RC _c = (BITCODE_RC)(value); \
407 GROUP (dxf); \
408 fwrite (&_c, 1, 1, dat->fh); \
409 }
410 #define VALUE_RS(value, dxf) \
411 { \
412 BITCODE_RS _s = (BITCODE_RS)(value); \
413 GROUP (dxf); \
414 fwrite (&_s, 2, 1, dat->fh); \
415 }
416 #define VALUE_RSd(value, dxf) \
417 { \
418 BITCODE_RSd _s = (BITCODE_RSd)(value); \
419 GROUP (dxf); \
420 fwrite (&_s, 2, 1, dat->fh); \
421 }
422 #define VALUE_RL(value, dxf) \
423 { \
424 BITCODE_RL _s = (BITCODE_RL)value; \
425 GROUP (dxf); \
426 fwrite (&_s, 4, 1, dat->fh); \
427 }
428 #define VALUE_RLL(value, dxf) \
429 { \
430 BITCODE_RLL _s = (BITCODE_RLL)value; \
431 GROUP (dxf); \
432 fwrite (&_s, 8, 1, dat->fh); \
433 }
434 // most DXFB FIELD_RC are written as int16 actually
435 // we need to check dwg_resbuf_value_type()
436 #define FIELD_RC(nam, dxf) VALUE_INT (_obj->nam, dxf)
437 #define VALUE_INT(value, dxf) \
438 { \
439 if (dxf == 0) \
440 VALUE_RS (value, dxf) \
441 else \
442 switch (dwg_resbuf_value_type (dxf)) \
443 { \
444 case DWG_VT_BOOL: \
445 case DWG_VT_INT8: \
446 VALUE_RC (value, dxf); \
447 break; \
448 case DWG_VT_INT16: \
449 VALUE_RS (value, dxf); \
450 break; \
451 case DWG_VT_INT32: \
452 VALUE_RL (value, dxf); \
453 break; \
454 case DWG_VT_INT64: \
455 VALUE_RLL (value, dxf); \
456 break; \
457 case DWG_VT_STRING: \
458 case DWG_VT_POINT3D: \
459 case DWG_VT_REAL: \
460 case DWG_VT_BINARY: \
461 case DWG_VT_HANDLE: \
462 case DWG_VT_OBJECTID: \
463 case DWG_VT_INVALID: \
464 default: \
465 LOG_ERROR ("Unhandled VALUE_INT code %d", dxf); \
466 } \
467 }
468
469 #define VALUE_3BD(value, dxf) \
470 { \
471 VALUE_RD (value.x, dxf); \
472 VALUE_RD (value.y, dxf + 10); \
473 VALUE_RD (value.z, dxf + 20); \
474 }
475 #define HEADER_RC(nam, dxf) \
476 { \
477 HEADER_9 (nam); \
478 VALUE_INT (dwg->header_vars.nam, dxf); \
479 }
480 #define HEADER_RC0(nam, dxf) \
481 if (dwg->header_vars.nam) \
482 { \
483 HEADER_9 (nam); \
484 VALUE_INT (dwg->header_vars.nam, dxf); \
485 }
486 #define HEADER_RS0(nam, dxf) \
487 if (dwg->header_vars.nam) \
488 { \
489 HEADER_9 (nam); \
490 VALUE_RS (dwg->header_vars.nam, dxf); \
491 }
492 #define HEADER_B(nam, dxf) HEADER_RC (nam, dxf)
493 #define FIELD_RS(nam, dxf) VALUE_INT (_obj->nam, dxf)
494 #define HEADER_RS(nam, dxf) \
495 { \
496 HEADER_9 (nam); \
497 VALUE_RS (dwg->header_vars.nam, dxf); \
498 }
499 #define HEADER_RSd(nam, dxf) \
500 { \
501 HEADER_9 (nam); \
502 VALUE_RSd (dwg->header_vars.nam, dxf); \
503 }
504 #define VALUE_RD(value, dxf) \
505 { \
506 double d = (value); \
507 GROUP (dxf); \
508 fwrite (&d, 8, 1, dat->fh); \
509 }
510 #define FIELD_RD(nam, dxf) VALUE_RD (_obj->nam, dxf)
511 #define HEADER_RD(nam, dxf) \
512 { \
513 HEADER_9 (nam); \
514 VALUE_RD (dwg->header_vars.nam, dxf); \
515 }
516
517 #define FIELD_RL(nam, dxf) VALUE_INT (_obj->nam, dxf)
518 #define HEADER_RL(nam, dxf) \
519 { \
520 HEADER_9 (nam); \
521 VALUE_RL (dwg->header_vars.nam, dxf); \
522 }
523
524 #define HEADER_B(nam, dxf) HEADER_RC (nam, dxf)
525 #define HEADER_BS(nam, dxf) HEADER_RS (nam, dxf)
526 #define HEADER_BSd(nam, dxf) HEADER_RS (nam, dxf)
527 #define HEADER_BD(nam, dxf) HEADER_RD (nam, dxf)
528 #define HEADER_BL(nam, dxf) HEADER_RL (nam, dxf)
529 #define HEADER_BLd(nam, dxf) HEADER_RL (nam, dxf)
530
531 #define FIELD_DATAHANDLE(nam, code, dxf) \
532 { \
533 Dwg_Object_Ref *ref = _obj->nam; \
534 HEADER_9 (nam); \
535 VALUE_H (ref ? ref->handleref.value : 0UL, dxf); \
536 }
537 // I would rather assume 8-byte LE
538 #define VALUE_H(value, dxf) \
539 if (dxf) \
540 { \
541 char _s[18]; \
542 snprintf (_s, sizeof (_s), FMT_H, (BITCODE_RLL)(value)); \
543 _s[sizeof (_s) - 1] = '\0'; \
544 VALUE_TV (_s, dxf); \
545 }
546 #define HEADER_H(nam, dxf) \
547 if (dxf) \
548 { \
549 HEADER_9 (nam); \
550 VALUE_HANDLE (dwg->header_vars.nam, nam, 0, dxf); \
551 }
552 #define HEADER_H0(nam, dxf) \
553 if (dxf && dwg->header_vars.nam && dwg->header_vars.nam->absolute_ref) \
554 { \
555 HEADER_9 (nam); \
556 VALUE_H (dwg->header_vars.nam->absolute_ref, dxf); \
557 }
558
559 #define HANDLE_NAME(nam, code, table) \
560 VALUE_HANDLE_NAME (dwg->header_vars.nam, dxf, table)
561 // TODO: convert STANDARD to Standard?
562 #define VALUE_HANDLE_NAME(value, dxf, table) \
563 { \
564 Dwg_Object_Ref *ref = value; \
565 if (ref && obj && obj->parent \
566 && (!ref->obj || ref->obj->supertype != DWG_SUPERTYPE_OBJECT \
567 || ref->obj->fixedtype != DWG_TYPE_##table)) \
568 ref->obj = dwg_resolve_handle (obj->parent, ref->absolute_ref); \
569 if (ref && ref->obj && ref->obj->supertype == DWG_SUPERTYPE_OBJECT \
570 && ref->obj->fixedtype == DWG_TYPE_##table) \
571 { \
572 VALUE_TV (ref->obj->tio.object->tio.table->name, dxf) \
573 } \
574 else \
575 VALUE_TV ("", dxf) \
576 }
577 #define FIELD_HANDLE_NAME(nam, dxf, table) \
578 VALUE_HANDLE_NAME (_obj->nam, dxf, table)
579 #define SUB_FIELD_HANDLE_NAME(ob, nam, dxf, table) \
580 VALUE_HANDLE_NAME (_obj->ob.nam, dxf, table)
581 #define HEADER_HANDLE_NAME(nam, dxf, table) \
582 HEADER_9 (nam); \
583 VALUE_HANDLE_NAME (dwg->header_vars.nam, dxf, table)
584
585 #define FIELD_BLL(nam, dxf) \
586 { \
587 BITCODE_BLL s = _obj->nam; \
588 GROUP (dxf); \
589 fwrite (&s, 8, 1, dat->fh); \
590 }
591 #define FIELD_RLL(nam, dxf) FIELD_BLL (nam, dxf)
592 #define HEADER_RLL(nam, dxf) \
593 { \
594 GROUP (9); \
595 fprintf (dat->fh, "$%s%c", #nam, 0); \
596 FIELD_BLL (nam, dxf); \
597 }
598
599 #define FIELD_MC(nam, dxf) FIELD_RC (nam, dxf)
600 #define FIELD_MS(nam, dxf) FIELD_RS (nam, dxf)
601 #define FIELD_BT(nam, dxf) FIELD_BD (nam, dxf);
602 #define FIELD_4BITS(nam, dxf) FIELD_RC (nam, dxf)
603 #define FIELD_BE(nam, dxf) \
604 { \
605 if (dxf \
606 && !(_obj->nam.x == 0.0 && _obj->nam.y == 0.0 && _obj->nam.z == 1.0)) \
607 FIELD_3RD (nam, dxf) \
608 }
609 #define FIELD_DD(nam, _default, dxf) FIELD_RD (nam, dxf)
610 #define FIELD_2DD(nam, def, dxf) \
611 if (dxf) \
612 { \
613 FIELD_DD (nam.x, FIELD_VALUE (def.x), dxf); \
614 FIELD_DD (nam.y, FIELD_VALUE (def.y), dxf + 10); \
615 }
616 #define FIELD_3DD(nam, def, dxf) \
617 if (dxf) \
618 { \
619 FIELD_DD (nam.x, FIELD_VALUE (def.x), dxf); \
620 FIELD_DD (nam.y, FIELD_VALUE (def.y), dxf + 10); \
621 FIELD_DD (nam.z, FIELD_VALUE (def.z), dxf + 20); \
622 }
623 #define FIELD_2RD(nam, dxf) \
624 if (dxf) \
625 { \
626 FIELD_RD (nam.x, dxf); \
627 FIELD_RD (nam.y, dxf + 10); \
628 }
629 #define FIELD_2RD0(nam, dxf) \
630 if (dxf && _obj->nam.x != 0.0 && _obj->nam.y != 0.0) \
631 { \
632 FIELD_RD (nam.x, dxf); \
633 FIELD_RD (nam.y, dxf + 10); \
634 }
635 #define FIELD_2BD(nam, dxf) FIELD_2RD (nam, dxf)
636 #define FIELD_2BD_1(nam, dxf) \
637 if (dxf) \
638 { \
639 FIELD_RD (nam.x, dxf); \
640 FIELD_RD (nam.y, dxf + 1); \
641 }
642 #define FIELD_3RD(nam, dxf) \
643 if (dxf) \
644 { \
645 FIELD_RD (nam.x, dxf); \
646 FIELD_RD (nam.y, dxf + 10); \
647 FIELD_RD (nam.z, dxf + 20); \
648 }
649 #define FIELD_3BD(nam, dxf) FIELD_3RD (nam, dxf)
650 #define FIELD_3BD_1(nam, dxf) \
651 if (dxf) \
652 { \
653 FIELD_RD (nam.x, dxf); \
654 FIELD_RD (nam.y, dxf + 1); \
655 FIELD_RD (nam.z, dxf + 2); \
656 }
657 #define FIELD_3DPOINT(nam, dxf) FIELD_3RD (nam, dxf)
658 #define FIELD_CMC(color, dxf) \
659 { \
660 if (dat->version < R_2004) \
661 { \
662 if (dat->from_version >= R_2004) \
663 bit_downconvert_CMC (dat, (Dwg_Color *)&_obj->color); \
664 VALUE_RS (_obj->color.index, dxf); \
665 } \
666 else \
667 { \
668 if (dat->from_version < R_2004) \
669 bit_upconvert_CMC (dat, (Dwg_Color *)&_obj->color); \
670 if (dxf >= 90) \
671 { \
672 VALUE_RL (_obj->color.rgb, dxf); \
673 } \
674 else if (_obj->color.method == 0xc3) \
675 { \
676 VALUE_RL (_obj->color.rgb & 0x00ffffff, dxf); \
677 } \
678 else if (_obj->color.method == 0xc8) \
679 { \
680 VALUE_RS (257, dxf); \
681 } \
682 else \
683 { \
684 VALUE_RS (_obj->color.index, dxf); \
685 if (_obj->color.method == 0xc2) \
686 VALUE_RL (_obj->color.rgb, (unsigned)(dxf + 420 - 62)); \
687 } \
688 } \
689 }
690 #define FIELD_CMC0(color, dxf) \
691 { \
692 if (dat->version < R_2004) \
693 { \
694 if (dat->from_version >= R_2004) \
695 bit_downconvert_CMC (dat, (Dwg_Color *)&_obj->color); \
696 if (_obj->color.index) \
697 VALUE_RS (_obj->color.index, dxf); \
698 } \
699 else \
700 { \
701 if (dat->from_version < R_2004) \
702 bit_upconvert_CMC (dat, (Dwg_Color *)&_obj->color); \
703 if (dxf >= 90) \
704 { \
705 VALUE_RL (_obj->color.rgb, dxf); \
706 } \
707 else if (_obj->color.method == 0xc3) \
708 { \
709 VALUE_RL (_obj->color.rgb & 0x00ffffff, dxf); \
710 } \
711 else if (_obj->color.method == 0xc8) \
712 { \
713 VALUE_RS (257, dxf); \
714 } \
715 else \
716 { \
717 if (_obj->color.index) \
718 VALUE_RS (_obj->color.index, dxf); \
719 if (_obj->color.method == 0xc2) \
720 VALUE_RL (_obj->color.rgb, (unsigned)(dxf + 420 - 62)); \
721 } \
722 } \
723 }
724 #define SUB_FIELD_CMC(o, color, dxf) \
725 { \
726 if (dat->version < R_2004) \
727 { \
728 if (dat->from_version >= R_2004) \
729 bit_downconvert_CMC (dat, (Dwg_Color *)&_obj->o.color); \
730 VALUE_RS (_obj->o.color.index, dxf); \
731 } \
732 else \
733 { \
734 if (dat->from_version < R_2004) \
735 bit_upconvert_CMC (dat, (Dwg_Color *)&_obj->o.color); \
736 if (dxf >= 90) \
737 { \
738 VALUE_RL (_obj->o.color.rgb, dxf); \
739 } \
740 else if (_obj->o.color.method == 0xc8) \
741 { \
742 VALUE_RS (257, dxf); \
743 } \
744 else if (_obj->o.color.method == 0xc3) \
745 { \
746 VALUE_RL (_obj->o.color.rgb & 0x00ffffff, dxf); \
747 } \
748 else \
749 { \
750 VALUE_RS (_obj->o.color.index, dxf); \
751 if (_obj->o.color.method == 0xc2) \
752 VALUE_RL (_obj->o.color.rgb, (unsigned)(dxf + 420 - 62)); \
753 } \
754 } \
755 }
756 #define HEADER_CMC(nam, dxf) \
757 { \
758 HEADER_9 (nam); \
759 VALUE_RS (dwg->header_vars.nam.index, dxf); \
760 }
761 #define HEADER_TIMEBLL(nam, dxf) \
762 { \
763 HEADER_9 (nam); \
764 FIELD_TIMEBLL (nam, dxf); \
765 }
766 #define FIELD_TIMEBLL(nam, dxf) VALUE_RD (_obj->nam.value, dxf)
767
768 // FIELD_VECTOR_N(nam, type, size):
769 // reads data of the type indicated by 'type' 'size' times and stores
770 // it all in the vector called 'nam'.
771 #define FIELD_VECTOR_N(nam, type, size, dxf) \
772 if (dxf && _obj->nam) \
773 { \
774 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
775 VALUE (_obj->nam[vcount], type, dxf); \
776 }
777 #define FIELD_VECTOR_T(nam, type, size, dxf) \
778 if (dxf && _obj->nam) \
779 { \
780 if (!IS_FROM_TU (dat)) \
781 { \
782 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
783 VALUE_TV (_obj->nam[vcount], dxf) \
784 } \
785 else \
786 { \
787 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
788 VALUE_TU (_obj->nam[vcount], dxf) \
789 } \
790 }
791
792 #define FIELD_VECTOR(nam, type, size, dxf) \
793 FIELD_VECTOR_N (nam, type, _obj->size, dxf)
794
795 #define FIELD_2RD_VECTOR(nam, size, dxf) \
796 if (dxf && _obj->nam) \
797 { \
798 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
799 { \
800 FIELD_2RD (nam[vcount], dxf); \
801 } \
802 }
803
804 #define FIELD_2DD_VECTOR(nam, size, dxf) \
805 FIELD_2RD (nam[0], dxf); \
806 if (dxf && _obj->nam) \
807 { \
808 for (vcount = 1; vcount < (BITCODE_BL)_obj->size; vcount++) \
809 { \
810 FIELD_2DD (nam[vcount], nam[vcount - 1], dxf); \
811 } \
812 }
813
814 #define FIELD_3DPOINT_VECTOR(nam, size, dxf) \
815 if (dxf && _obj->nam) \
816 { \
817 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
818 { \
819 FIELD_3DPOINT (nam[vcount], dxf); \
820 } \
821 }
822
823 #define HANDLE_VECTOR_N(nam, size, code, dxf) \
824 if (dxf && _obj->nam) \
825 { \
826 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
827 { \
828 FIELD_HANDLE_N (nam[vcount], vcount, code, dxf); \
829 } \
830 }
831
832 #define HANDLE_VECTOR(nam, sizefield, code, dxf) \
833 HANDLE_VECTOR_N (nam, FIELD_VALUE (sizefield), code, dxf)
834
835 #define FIELD_NUM_INSERTS(num_inserts, type, dxf) \
836 FIELDG (num_inserts, type, dxf)
837
838 #define FIELD_XDATA(nam, size) \
839 dxfb_write_xdata (dat, obj, _obj->nam, _obj->size)
840
841 #define _XDICOBJHANDLE(code) \
842 if (dat->version >= R_13b1 && obj->tio.object->xdicobjhandle \
843 && obj->tio.object->xdicobjhandle->absolute_ref) \
844 { \
845 VALUE_TV ("{ACAD_XDICTIONARY", 102); \
846 VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, \
847 360); \
848 VALUE_TV ("}", 102); \
849 }
850 #define _REACTORS(code) \
851 if (dat->version >= R_13b1 && obj->tio.object->num_reactors \
852 && obj->tio.object->reactors) \
853 { \
854 VALUE_TV ("{ACAD_REACTORS", 102) \
855 for (vcount = 0; vcount < obj->tio.object->num_reactors; vcount++) \
856 { \
857 VALUE_HANDLE (obj->tio.object->reactors[vcount], reactors, code, \
858 330); \
859 } \
860 VALUE_TV ("}", 102) \
861 }
862 #define ENT_REACTORS(code) \
863 if (dat->version >= R_13b1 && _obj->num_reactors && _obj->reactors) \
864 { \
865 VALUE_TV ("{ACAD_REACTORS", 102) \
866 for (vcount = 0; vcount < _obj->num_reactors; vcount++) \
867 { \
868 VALUE_HANDLE (_obj->reactors[vcount], reactors, code, 330); \
869 } \
870 VALUE_TV ("}", 102) \
871 }
872
873 #define REACTORS(code)
874 #define XDICOBJHANDLE(code)
875 #define ENT_XDICOBJHANDLE(code) \
876 if (dat->version >= R_13b1 && obj->tio.entity->xdicobjhandle \
877 && obj->tio.entity->xdicobjhandle->absolute_ref) \
878 { \
879 VALUE_TV ("{ACAD_XDICTIONARY", 102); \
880 VALUE_HANDLE (obj->tio.entity->xdicobjhandle, xdicobjhandle, code, \
881 360); \
882 VALUE_TV ("}", 102); \
883 }
884 #define BLOCK_NAME(nam, dxf) dxfb_cvt_blockname (dat, _obj->nam, dxf)
885
886 #define COMMON_ENTITY_HANDLE_DATA
887 #define SECTION_STRING_STREAM
888 #define START_STRING_STREAM
889 #define END_STRING_STREAM
890 #define START_HANDLE_STREAM
891
892 #ifndef DEBUG_CLASSES
893 static int
894 dwg_dxfb_TABLECONTENT (Bit_Chain *restrict dat, const Dwg_Object *restrict obj)
895 {
896 (void)dat;
897 (void)obj;
898 return 0;
899 }
900 #else
901 static int dwg_dxfb_TABLECONTENT (Bit_Chain *restrict dat,
902 const Dwg_Object *restrict obj);
903 #endif
904
905 #define DWG_ENTITY(token) \
906 static int dwg_dxfb_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat, \
907 Bit_Chain *str_dat, \
908 const Dwg_Object *restrict obj); \
909 static int dwg_dxfb_##token (Bit_Chain *restrict dat, \
910 const Dwg_Object *restrict obj) \
911 { \
912 int error = 0; \
913 Bit_Chain *hdl_dat = dat; \
914 Bit_Chain *str_dat = dat; \
915 if (obj->fixedtype != DWG_TYPE_##token) \
916 { \
917 LOG_ERROR ("Invalid type 0x%x, expected 0x%x %s", obj->fixedtype, \
918 DWG_TYPE_##token, #token); \
919 return DWG_ERR_INVALIDTYPE; \
920 } \
921 if (strEQc (#token, "GEOPOSITIONMARKER")) \
922 RECORD (POSITIONMARKER) \
923 else if (dat->version < R_13b1 && strlen (#token) == 10 \
924 && strEQc (#token, "LWPOLYLINE")) \
925 RECORD (POLYLINE) \
926 else if (strlen (#token) > 10 && !memcmp (#token, "DIMENSION_", 10)) \
927 RECORD (DIMENSION) \
928 else if (strlen (#token) > 9 && !memcmp (#token, "POLYLINE_", 9)) \
929 RECORD (POLYLINE) \
930 else if (strlen (#token) > 7 && !memcmp (#token, "VERTEX_", 7)) \
931 RECORD (VERTEX) \
932 else if (strEQc (#token, "MINSERT")) \
933 RECORD (INSERT) \
934 else if (dat->version >= R_2010 && strEQc (#token, "TABLE")) \
935 { \
936 RECORD (ACAD_TABLE); \
937 return dwg_dxfb_TABLECONTENT (dat, obj); \
938 } \
939 else if (strlen (#token) > 3 && !memcmp (#token, "_3D", 3)) \
940 VALUE_TV (obj->dxfname, 0) \
941 else if (obj->type >= 498 && obj->dxfname) \
942 VALUE_TV (obj->dxfname, 0) \
943 else \
944 RECORD (token) \
945 LOG_INFO ("Entity " #token ":\n") \
946 SINCE (R_11) \
947 { \
948 LOG_TRACE ("Entity handle: " FORMAT_H "\n", ARGS_H (obj->handle)) \
949 VALUE_H (obj->handle.value, 5); \
950 } \
951 SINCE (R_13b1) \
952 { \
953 VALUE_HANDLE_NAME (obj->parent->header_vars.BLOCK_RECORD_MSPACE, 330, \
954 BLOCK_HEADER); \
955 } \
956 error |= dxfb_common_entity_handle_data (dat, obj); \
957 error |= dwg_dxfb_##token##_private (dat, hdl_dat, str_dat, obj); \
958 error |= dxfb_write_eed (dat, obj->tio.object); \
959 return error; \
960 } \
961 static int dwg_dxfb_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat, \
962 Bit_Chain *str_dat, \
963 const Dwg_Object *restrict obj) \
964 { \
965 int error = 0; \
966 BITCODE_BL vcount, rcount3, rcount4; \
967 Dwg_Data *dwg = obj->parent; \
968 Dwg_Entity_##token *_obj = obj->tio.entity->tio.token; \
969 Dwg_Object_Entity *_ent = obj->tio.entity;
970
971 #define DWG_ENTITY_END \
972 return error; \
973 }
974
975 #define DWG_OBJECT(token) \
976 static int dwg_dxfb_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat, \
977 Bit_Chain *str_dat, \
978 const Dwg_Object *restrict obj); \
979 static int dwg_dxfb_##token (Bit_Chain *restrict dat, \
980 const Dwg_Object *restrict obj) \
981 { \
982 BITCODE_BL vcount; \
983 int error = 0; \
984 Bit_Chain *str_dat = dat; \
985 Bit_Chain *hdl_dat = dat; \
986 LOG_INFO ("Object " #token ":\n") \
987 if (obj->fixedtype != DWG_TYPE_##token) \
988 { \
989 LOG_ERROR ("Invalid type 0x%x, expected 0x%x %s", obj->fixedtype, \
990 DWG_TYPE_##token, #token); \
991 return DWG_ERR_INVALIDTYPE; \
992 } \
993 PRE (R_14) \
994 { \
995 if (obj->fixedtype == DWG_TYPE_PLACEHOLDER) \
996 return 0; \
997 } \
998 if (!dwg_obj_is_control (obj)) \
999 { \
1000 if (obj->fixedtype == DWG_TYPE_TABLE) \
1001 ; \
1002 else if (obj->type >= 500 && obj->dxfname) \
1003 VALUE_TV (obj->dxfname, 0) \
1004 else if (obj->type == DWG_TYPE_PLACEHOLDER) \
1005 RECORD (ACDBPLACEHOLDER) \
1006 else if (obj->fixedtype == DWG_TYPE_PROXY_OBJECT) \
1007 RECORD (ACAD_PROXY_OBJECT) \
1008 else if (obj->type != DWG_TYPE_BLOCK_HEADER) \
1009 RECORD (token) \
1010 SINCE (R_13b1) \
1011 { \
1012 const int dxf = obj->type == DWG_TYPE_DIMSTYLE ? 105 : 5; \
1013 VALUE_H (obj->handle.value, dxf); \
1014 _XDICOBJHANDLE (3); \
1015 _REACTORS (4); \
1016 } \
1017 SINCE (R_14) \
1018 { \
1019 VALUE_HANDLE (obj->tio.object->ownerhandle, ownerhandle, 3, 330); \
1020 } \
1021 } \
1022 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE) \
1023 { \
1024 if (dwg_obj_is_table (obj)) \
1025 { \
1026 char *_name = dwg_obj_table_get_name (obj, &error); \
1027 LOG_TRACE ("Object handle: " FORMAT_H ", name: %s\n", \
1028 ARGS_H (obj->handle), _name); \
1029 if (IS_FROM_TU (dat)) \
1030 free (_name); \
1031 } \
1032 else \
1033 LOG_TRACE ("Object handle: " FORMAT_H "\n", ARGS_H (obj->handle)) \
1034 } \
1035 error |= dwg_dxfb_##token##_private (dat, hdl_dat, str_dat, obj); \
1036 error |= dxfb_write_eed (dat, obj->tio.object); \
1037 return error; \
1038 } \
1039 static int dwg_dxfb_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat, \
1040 Bit_Chain *str_dat, \
1041 const Dwg_Object *restrict obj) \
1042 { \
1043 int error = 0; \
1044 BITCODE_BL vcount, rcount3, rcount4; \
1045 Dwg_Data *dwg = obj->parent; \
1046 Dwg_Object_##token *_obj = obj->tio.object->tio.token;
1047
1048 // then 330, SUBCLASS
1049
1050 #define DWG_OBJECT_END \
1051 return error; \
1052 }
1053
1054 static int
1055 dxfb_write_eed (Bit_Chain *restrict dat, const Dwg_Object_Object *restrict obj)
1056 {
1057 int error = 0;
1058 Dwg_Data *dwg = obj->dwg;
1059 for (BITCODE_BL i = 0; i < obj->num_eed; i++)
1060 {
1061 const Dwg_Eed *_obj = &obj->eed[i];
1062 if (_obj->size)
1063 {
1064 // name of APPID
1065 Dwg_Object *appid = dwg_resolve_handle (dwg, _obj->handle.value);
1066 if (appid && appid->fixedtype == DWG_TYPE_APPID)
1067 VALUE_T (appid->tio.object->tio.APPID->name, 1001)
1068 else
1069 VALUE_TFF ("ACAD", 1001);
1070 }
1071 if (_obj->data)
1072 {
1073 const Dwg_Eed_Data *data = _obj->data;
1074 const int dxf = data->code + 1000;
1075 switch (data->code)
1076 {
1077 case 0:
1078 if (IS_FROM_TU (dat))
1079 VALUE_TU (data->u.eed_0_r2007.string, 1000)
1080 else
1081 VALUE_TV (data->u.eed_0.string, 1000)
1082 break;
1083 case 2:
1084 if (data->u.eed_2.close)
1085 VALUE_TFF ("}", 1002)
1086 else
1087 VALUE_TFF ("{", 1002)
1088 break;
1089 case 3:
1090 GROUP (dxf);
1091 fprintf (dat->fh, "%9lu\r\n",
1092 (unsigned long)data->u.eed_3.layer);
1093 // VALUE_RLL (data->u.eed_3.layer, dxf);
1094 break;
1095 case 4:
1096 VALUE_BINARY (data->u.eed_4.data, data->u.eed_4.length, dxf);
1097 break;
1098 case 5:
1099 VALUE_H (data->u.eed_5.entity, dxf);
1100 break; // not in DXF
1101 case 10:
1102 case 11:
1103 case 12:
1104 case 13:
1105 case 14:
1106 case 15:
1107 VALUE_3BD (data->u.eed_10.point, dxf);
1108 break;
1109 case 40:
1110 case 41:
1111 case 42:
1112 VALUE_RD (data->u.eed_40.real, dxf);
1113 break;
1114 case 70:
1115 VALUE_RS (data->u.eed_70.rs, dxf);
1116 break;
1117 case 71:
1118 VALUE_RL (data->u.eed_71.rl, dxf);
1119 break;
1120 default:
1121 VALUE_RC (0, dxf);
1122 }
1123 }
1124 }
1125 return error;
1126 }
1127
1128 static void
1129 dxfb_write_xdata (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
1130 Dwg_Resbuf *restrict rbuf, BITCODE_BL size)
1131 {
1132 Dwg_Resbuf *tmp;
1133 int i;
1134
1135 while (rbuf)
1136 {
1137 // const char* fmt = dxf_format(rbuf->type);
1138 short type = dwg_resbuf_value_type (rbuf->type);
1139 int dxftype = (rbuf->type > 1000 || obj->fixedtype == DWG_TYPE_XRECORD)
1140 ? rbuf->type
1141 : rbuf->type + 1000;
1142
1143 tmp = rbuf->nextrb;
1144 switch (type)
1145 {
1146 case DWG_VT_STRING:
1147 if (IS_FROM_TU (dat))
1148 {
1149 VALUE_TU (rbuf->value.str.u.wdata, dxftype);
1150 }
1151 else
1152 {
1153 VALUE_TV (rbuf->value.str.u.data, dxftype);
1154 }
1155 break;
1156 case DWG_VT_REAL:
1157 VALUE_RD (rbuf->value.dbl, dxftype);
1158 break;
1159 case DWG_VT_BOOL:
1160 case DWG_VT_INT8:
1161 VALUE_RC (rbuf->value.i8, dxftype);
1162 break;
1163 case DWG_VT_INT16:
1164 VALUE_RS (rbuf->value.i16, dxftype);
1165 break;
1166 case DWG_VT_INT32:
1167 VALUE_RL (rbuf->value.i32, dxftype);
1168 break;
1169 case DWG_VT_INT64:
1170 VALUE_RLL (rbuf->value.i64, dxftype);
1171 break;
1172 case DWG_VT_POINT3D:
1173 VALUE_RD (rbuf->value.pt[0], dxftype);
1174 VALUE_RD (rbuf->value.pt[1], dxftype + 10);
1175 VALUE_RD (rbuf->value.pt[2], dxftype + 20);
1176 break;
1177 case DWG_VT_BINARY:
1178 VALUE_BINARY (rbuf->value.str.u.data, rbuf->value.str.size, dxftype);
1179 break;
1180 case DWG_VT_HANDLE:
1181 case DWG_VT_OBJECTID:
1182 VALUE_H (rbuf->value.absref, dxftype);
1183 break;
1184 case DWG_VT_INVALID:
1185 default:
1186 // fprintf(dat->fh, "");
1187 break;
1188 }
1189 rbuf = tmp;
1190 }
1191 }
1192
1193 #undef DXF_3DSOLID
1194 #define DXF_3DSOLID dxfb_3dsolid (dat, obj, (Dwg_Entity_3DSOLID *)_obj);
1195
1196 // r13+ converts STANDARD to Standard, BYLAYER to ByLayer, BYBLOCK to ByBlock
1197 static void
1198 dxfb_cvt_tablerecord (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
1199 char *restrict name, const int dxf)
1200 {
1201 if (obj && obj->supertype == DWG_SUPERTYPE_OBJECT && name)
1202 {
1203 if (IS_FROM_TU (dat))
1204 {
1205 name = bit_convert_TU ((BITCODE_TU)name);
1206 }
1207 if (dat->from_version >= R_13b1 && dat->version < R_13b1)
1208 { // convert the other way round, from newer to older
1209 if (strEQc (name, "Standard"))
1210 VALUE_TV ("STANDARD", dxf)
1211 else if (strEQc (name, "ByLayer"))
1212 VALUE_TV ("BYLAYER", dxf)
1213 else if (strEQc (name, "ByBlock"))
1214 VALUE_TV ("BYBLOCK", dxf)
1215 else if (strEQc (name, "*Active"))
1216 VALUE_TV ("*ACTIVE", dxf)
1217 else
1218 VALUE_TV (name, dxf)
1219 }
1220 else
1221 { // convert some standard names
1222 if (dat->version >= R_13b1 && strEQc (name, "STANDARD"))
1223 VALUE_TV ("Standard", dxf)
1224 else if (dat->version >= R_13b1 && strEQc (name, "BYLAYER"))
1225 VALUE_TV ("ByLayer", dxf)
1226 else if (dat->version >= R_13b1 && strEQc (name, "BYBLOCK"))
1227 VALUE_TV ("ByBlock", dxf)
1228 else if (dat->version >= R_13b1 && strEQc (name, "*ACTIVE"))
1229 VALUE_TV ("*Active", dxf)
1230 else
1231 VALUE_TV (name, dxf)
1232 }
1233 if (IS_FROM_TU (dat))
1234 free (name);
1235 }
1236 else
1237 {
1238 VALUE_TV ("", dxf)
1239 }
1240 }
1241
1242 /* pre-r13 mspace and pspace blocks have different names:
1243 *Model_Space => $MODEL_SPACE
1244 *Paper_Space => $PAPER_SPACE
1245 */
1246 static void
1247 dxfb_cvt_blockname (Bit_Chain *restrict dat, char *restrict name,
1248 const int dxf)
1249 {
1250 if (!name)
1251 {
1252 VALUE_TV ("", dxf)
1253 return;
1254 }
1255 if (IS_FROM_TU (dat)) // r2007+ unicode names
1256 {
1257 name = bit_convert_TU ((BITCODE_TU)name);
1258 }
1259 if (dat->version == dat->from_version) // no conversion
1260 {
1261 VALUE_TV (name, dxf)
1262 }
1263 else if (dat->version < R_13b1 && dat->from_version >= R_13b1) // to older
1264 {
1265 if (strlen (name) < 10)
1266 VALUE_TV (name, dxf)
1267 else if (strEQc (name, "*Model_Space"))
1268 VALUE_TV ("$MODEL_SPACE", dxf)
1269 else if (strEQc (name, "*Paper_Space"))
1270 VALUE_TV ("$PAPER_SPACE", dxf)
1271 else if (!memcmp (name, "*Paper_Space", sizeof ("*Paper_Space") - 1))
1272 {
1273 GROUP (dxf);
1274 fprintf (dat->fh, "$PAPER_SPACE%s%c", &name[12], 0);
1275 }
1276 else
1277 VALUE_TV (name, dxf)
1278 }
1279 else if (dat->version >= R_13b1 && dat->from_version < R_13b1) // to newer
1280 {
1281 if (strlen (name) < 10)
1282 VALUE_TV (name, dxf)
1283 else if (strEQc (name, "$MODEL_SPACE"))
1284 VALUE_TV ("*Model_Space", dxf)
1285 else if (strEQc (name, "$PAPER_SPACE"))
1286 VALUE_TV ("*Paper_Space", dxf)
1287 else if (!memcmp (name, "$PAPER_SPACE", sizeof ("$PAPER_SPACE") - 1))
1288 {
1289 GROUP (dxf);
1290 fprintf (dat->fh, "*Paper_Space%s%c", &name[12], 0);
1291 }
1292 else
1293 VALUE_TV (name, dxf)
1294 }
1295 if (IS_FROM_TU (dat))
1296 free (name);
1297 }
1298
1299 #define START_OBJECT_HANDLE_STREAM
1300
1301 // Handle 5 written here first
1302 #define COMMON_TABLE_CONTROL_FLAGS \
1303 if (ctrl) \
1304 { \
1305 SINCE (R_13b1) \
1306 { \
1307 BITCODE_BL vcount; \
1308 VALUE_H (ctrl->handle.value, 5); \
1309 _XDICOBJHANDLE (3); \
1310 _REACTORS (4); \
1311 } \
1312 SINCE (R_14) \
1313 { \
1314 VALUE_HANDLE (ctrl->tio.object->ownerhandle, ownerhandle, 3, 330); \
1315 } \
1316 } \
1317 SINCE (R_13b1) \
1318 { \
1319 VALUE_TV ("AcDbSymbolTable", 100); \
1320 }
1321
1322 #define COMMON_TABLE_FLAGS(acdbname) \
1323 SINCE (R_13b1) \
1324 { \
1325 VALUE_TV ("AcDbSymbolTableRecord", 100) \
1326 VALUE_TV ("AcDb" #acdbname "TableRecord", 100) \
1327 } \
1328 if (strEQc (#acdbname, "Block") && dat->version >= R_13b1) \
1329 { \
1330 Dwg_Object *blk = dwg_ref_object ( \
1331 dwg, ((Dwg_Object_BLOCK_HEADER *)_obj)->block_entity); \
1332 if (blk && blk->type == DWG_TYPE_BLOCK) \
1333 { \
1334 Dwg_Entity_BLOCK *_blk = blk->tio.entity->tio.BLOCK; \
1335 VALUE_T (_blk->name, 2) \
1336 } \
1337 else if (_obj->name) \
1338 { \
1339 VALUE_T (_obj->name, 2) \
1340 } \
1341 else \
1342 VALUE_TV ("*", 2) \
1343 } \
1344 /* Empty name with xref shape names */ \
1345 else if (strEQc (#acdbname, "TextStyle") && _obj->flag & 1 \
1346 && dxf_is_xrefdep_name (dat, _obj->name)) \
1347 VALUE_TV ("", 2) \
1348 else if (_obj->name) \
1349 dxfb_cvt_tablerecord (dat, obj, _obj->name, 2); \
1350 else \
1351 VALUE_TV ("*", 2) \
1352 if (strEQc (#acdbname, "Layer") && dat->version >= R_2000) \
1353 { \
1354 /* Mask off plotflag and linewt. */ \
1355 BITCODE_RC _flag = _obj->flag & ~0x3e0; \
1356 /* Don't keep bit 16 when not xrefdep like "XREF|name" */ \
1357 if (_flag & 0x10 && !dxf_has_xrefdep_vertbar (dat, _obj->name)) \
1358 _flag &= ~0x10; \
1359 VALUE_RC (_flag, 70); \
1360 } \
1361 else if (strEQc (#acdbname, "Block") && dat->version >= R_2000) \
1362 ; /* skip 70 for AcDbBlockTableRecord here. done in AcDbBlockBegin */ \
1363 else \
1364 { \
1365 /* mask off 64, the loaded bit 6 */ \
1366 VALUE_RS (_obj->flag & ~64, 70); \
1367 }
1368
1369 #define LAYER_TABLE_FLAGS(acdbname) \
1370 SINCE (R_14) \
1371 { \
1372 VALUE_HANDLE (obj->tio.object->ownerhandle, ownerhandle, 3, 330); \
1373 } \
1374 SINCE (R_13b1) \
1375 { \
1376 VALUE_TV ("AcDbSymbolTableRecord", 100) \
1377 VALUE_TV ("AcDb" #acdbname "TableRecord", 100) \
1378 } \
1379 if (_obj->name) \
1380 dxfb_cvt_tablerecord (dat, obj, _obj->name, 2); \
1381 FIELD_RS (flag, 70)
1382
1383 #include "dwg.spec"
1384
1385 static int
1386 dxfb_3dsolid (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
1387 Dwg_Entity_3DSOLID *restrict _obj)
1388 {
1389 BITCODE_BL i;
1390 int error = 0;
1391
1392 COMMON_ENTITY_HANDLE_DATA;
1393 SUBCLASS (AcDbModelerGeometry);
1394
1395 FIELD_B (acis_empty, 0);
1396 if (!FIELD_VALUE (acis_empty))
1397 {
1398 FIELD_B (unknown, 0);
1399 FIELD_BS (version, 70);
1400 if (FIELD_VALUE (version) == 1)
1401 {
1402 for (i = 0; i < FIELD_VALUE (num_blocks); i++)
1403 {
1404 char *s = FIELD_VALUE (encr_sat_data[i]);
1405 int len = FIELD_VALUE (block_size[i]);
1406 // DXF 1 + 3 if >255
1407 while (len > 0)
1408 {
1409 char *n = strchr (s, '\n');
1410 int l = len > 255 ? 255 : len & 0xff;
1411 if (n && ((long)(n - s) < (long)len))
1412 {
1413 l = n - s;
1414 }
1415 if (l)
1416 {
1417 if (len < 255)
1418 VALUE_BINARY (s, l, 1)
1419 else
1420 VALUE_BINARY (s, l, 3)
1421 l++;
1422 len -= l;
1423 s += l;
1424 }
1425 else
1426 {
1427 len--;
1428 s++;
1429 }
1430 }
1431 }
1432 // LOG_TRACE("acis_data [1]:\n%s\n", FIELD_VALUE (acis_data));
1433 }
1434 else // if (FIELD_VALUE(version)==2)
1435 // must use ASCII out
1436 {
1437 LOG_ERROR ("ACIS BinaryFile v2 not yet supported. Use ASCII output.");
1438 }
1439 }
1440 return error;
1441 }
1442
1443 /* returns 0 on success
1444 */
1445 static int
1446 dwg_dxfb_variable_type (const Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
1447 Dwg_Object *restrict obj)
1448 {
1449 int i;
1450 Dwg_Class *klass;
1451 int is_entity;
1452
1453 i = obj->type - 500;
1454 if (i < 0 || i >= dwg->num_classes)
1455 return DWG_ERR_INVALIDTYPE;
1456 if (obj->fixedtype == DWG_TYPE_UNKNOWN_ENT
1457 || obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ)
1458 return DWG_ERR_UNHANDLEDCLASS;
1459
1460 klass = &dwg->dwg_class[i];
1461 if (!klass || !klass->dxfname)
1462 return DWG_ERR_INTERNALERROR;
1463 // almost always false
1464 is_entity = dwg_class_is_entity (klass);
1465 if (dat->version < R_2000)
1466 {
1467 // keep only: IMAGE, LWPOLYLINE, HATCH
1468 if (is_entity && strNE (klass->dxfname, "IMAGE")
1469 && strNEc (klass->dxfname, "LWPOLYLINE")
1470 && strNEc (klass->dxfname, "HATCH"))
1471 {
1472 LOG_WARN ("Skip %s\n", klass->dxfname)
1473 return DWG_ERR_UNHANDLEDCLASS;
1474 }
1475 // keep only: DICTIONARYVAR, MATERIAL, RASTERVARIABLES, IMAGEDEF_REACTOR,
1476 // XRECORD
1477 else if (!is_entity && strNEc (klass->dxfname, "DICTIONARYVAR")
1478 && strNEc (klass->dxfname, "MATERIAL")
1479 && strNEc (klass->dxfname, "RASTERVARIABLES")
1480 && strNEc (klass->dxfname, "IDBUFFER")
1481 && strNEc (klass->dxfname, "IMAGEDEF_REACTOR")
1482 && strNEc (klass->dxfname, "XRECORD"))
1483 {
1484 LOG_WARN ("Skip %s\n", klass->dxfname)
1485 return DWG_ERR_UNHANDLEDCLASS;
1486 }
1487 }
1488
1489 // clang-format off
1490 #include "classes.inc"
1491 // clang-format on
1492
1493 return DWG_ERR_UNHANDLEDCLASS;
1494 }
1495
1496 /* process unsorted vertices */
1497 #define decl_dxfb_process_VERTEX(token) \
1498 static int dxfb_process_VERTEX_##token (Bit_Chain *restrict dat, \
1499 const Dwg_Object *restrict obj, \
1500 int *restrict i) \
1501 { \
1502 int error = 0; \
1503 Dwg_Entity_POLYLINE_##token *_obj \
1504 = obj->tio.entity->tio.POLYLINE_##token; \
1505 \
1506 VERSIONS (R_13b1, R_2000) \
1507 { \
1508 Dwg_Object *last_vertex \
1509 = _obj->last_vertex ? _obj->last_vertex->obj : NULL; \
1510 Dwg_Object *o = _obj->first_vertex ? _obj->first_vertex->obj : NULL; \
1511 if (!o || !last_vertex) \
1512 return DWG_ERR_INVALIDHANDLE; \
1513 if (o->fixedtype == DWG_TYPE_VERTEX_##token) \
1514 error |= dwg_dxfb_VERTEX_##token (dat, o); \
1515 *i = *i + 1; \
1516 do \
1517 { \
1518 o = dwg_next_object (o); \
1519 if (!o) \
1520 return DWG_ERR_INVALIDHANDLE; \
1521 if (strEQc (#token, "PFACE") \
1522 && o->fixedtype == DWG_TYPE_VERTEX_PFACE_FACE) \
1523 { \
1524 error |= dwg_dxfb_VERTEX_PFACE_FACE (dat, o); \
1525 } \
1526 else if (o->fixedtype == DWG_TYPE_VERTEX_##token) \
1527 { \
1528 error |= dwg_dxfb_VERTEX_##token (dat, o); \
1529 } \
1530 *i = *i + 1; \
1531 } \
1532 while (o->fixedtype != DWG_TYPE_SEQEND && o != last_vertex); \
1533 o = _obj->seqend ? _obj->seqend->obj : NULL; \
1534 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
1535 error |= dwg_dxfb_SEQEND (dat, o); \
1536 *i = *i + 1; \
1537 } \
1538 SINCE (R_2004) \
1539 { \
1540 Dwg_Object *o; \
1541 for (BITCODE_BL j = 0; j < _obj->num_owned; j++) \
1542 { \
1543 o = _obj->vertex && _obj->vertex[j] ? _obj->vertex[j]->obj : NULL; \
1544 if (strEQc (#token, "PFACE") && o \
1545 && o->fixedtype == DWG_TYPE_VERTEX_PFACE_FACE) \
1546 { \
1547 error |= dwg_dxfb_VERTEX_PFACE_FACE (dat, o); \
1548 } \
1549 else if (o && o->fixedtype == DWG_TYPE_VERTEX_##token) \
1550 { \
1551 error |= dwg_dxfb_VERTEX_##token (dat, o); \
1552 } \
1553 } \
1554 o = _obj->seqend ? _obj->seqend->obj : NULL; \
1555 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
1556 error |= dwg_dxfb_SEQEND (dat, o); \
1557 *i = *i + _obj->num_owned + 1; \
1558 } \
1559 return error; \
1560 }
1561
1562 // clang-format off
1563 decl_dxfb_process_VERTEX (2D)
1564 decl_dxfb_process_VERTEX (3D)
1565 decl_dxfb_process_VERTEX (MESH)
1566 decl_dxfb_process_VERTEX (PFACE)
1567 // clang-format on
1568
1569 /* process seqend before attribs */
1570 #define decl_dxfb_process_INSERT(token) \
1571 static int dxfb_process_##token (Bit_Chain *restrict dat, \
1572 const Dwg_Object *restrict obj, \
1573 int *restrict i) \
1574 { \
1575 int error = 0; \
1576 Dwg_Entity_##token *_obj = obj->tio.entity->tio.token; \
1577 if (!_obj->has_attribs) \
1578 return 0; \
1579 \
1580 VERSIONS (R_13b1, R_2000) \
1581 { \
1582 Dwg_Object *last_attrib \
1583 = _obj->last_attrib ? _obj->last_attrib->obj : NULL; \
1584 Dwg_Object *o = _obj->first_attrib ? _obj->first_attrib->obj : NULL; \
1585 if (!o || !last_attrib) \
1586 return DWG_ERR_INVALIDHANDLE; \
1587 if (o->fixedtype == DWG_TYPE_ATTRIB) \
1588 error |= dwg_dxfb_ATTRIB (dat, o); \
1589 *i = *i + 1; \
1590 do \
1591 { \
1592 o = dwg_next_object (o); \
1593 if (!o) \
1594 return DWG_ERR_INVALIDHANDLE; \
1595 if (o->fixedtype == DWG_TYPE_ATTRIB) \
1596 error |= dwg_dxfb_ATTRIB (dat, o); \
1597 *i = *i + 1; \
1598 } \
1599 while (o->fixedtype == DWG_TYPE_ATTRIB && o != last_attrib); \
1600 o = _obj->seqend ? _obj->seqend->obj : NULL; \
1601 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
1602 error |= dwg_dxfb_SEQEND (dat, o); \
1603 *i = *i + 1; \
1604 } \
1605 SINCE (R_2004) \
1606 { \
1607 Dwg_Object *o; \
1608 for (BITCODE_BL j = 0; j < _obj->num_owned; j++) \
1609 { \
1610 o = _obj->attribs && _obj->attribs[j] ? _obj->attribs[j]->obj \
1611 : NULL; \
1612 if (o && o->fixedtype == DWG_TYPE_ATTRIB) \
1613 error |= dwg_dxfb_ATTRIB (dat, o); \
1614 } \
1615 o = _obj->seqend ? _obj->seqend->obj : NULL; \
1616 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
1617 error |= dwg_dxfb_SEQEND (dat, o); \
1618 *i = *i + _obj->num_owned + 1; \
1619 } \
1620 return error; \
1621 }
1622
1623 // clang-format off
1624 decl_dxfb_process_INSERT (INSERT)
1625 decl_dxfb_process_INSERT (MINSERT)
1626 // clang-format on
1627
1628 static int dwg_dxfb_object (Bit_Chain *restrict dat,
1629 const Dwg_Object *restrict obj,
1630 int *restrict i)
1631 {
1632 int error = 0;
1633 int minimal;
1634 unsigned int type;
1635
1636 if (!obj || !obj->parent)
1637 return DWG_ERR_INTERNALERROR;
1638 minimal = obj->parent->opts & DWG_OPTS_MINIMAL;
1639 if (dat->version < R_13b1)
1640 type = (unsigned int)obj->fixedtype;
1641 else
1642 {
1643 type = obj->type;
1644 if (obj->fixedtype == DWG_TYPE_UNKNOWN_ENT)
1645 type = DWG_TYPE_UNKNOWN_ENT;
1646 if (obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ)
1647 type = DWG_TYPE_UNKNOWN_OBJ;
1648 }
1649
1650 switch (type)
1651 {
1652 case DWG_TYPE_TEXT:
1653 return dwg_dxfb_TEXT (dat, obj);
1654 case DWG_TYPE_ATTDEF:
1655 return dwg_dxfb_ATTDEF (dat, obj);
1656 case DWG_TYPE_BLOCK:
1657 return dwg_dxfb_BLOCK (dat, obj);
1658 case DWG_TYPE_ENDBLK:
1659 LOG_WARN ("stale %s subentity", obj->dxfname);
1660 return 0; // dwg_dxfb_ENDBLK(dat, obj);
1661 case DWG_TYPE_SEQEND:
1662 LOG_WARN ("stale %s subentity", obj->dxfname);
1663 return 0; // dwg_dxfb_SEQEND(dat, obj);
1664
1665 case DWG_TYPE_INSERT:
1666 error = dwg_dxfb_INSERT (dat, obj);
1667 return error | dxfb_process_INSERT (dat, obj, i);
1668 case DWG_TYPE_MINSERT:
1669 error = dwg_dxfb_MINSERT (dat, obj);
1670 return error | dxfb_process_MINSERT (dat, obj, i);
1671 case DWG_TYPE_POLYLINE_2D:
1672 error = dwg_dxfb_POLYLINE_2D (dat, obj);
1673 return error | dxfb_process_VERTEX_2D (dat, obj, i);
1674 case DWG_TYPE_POLYLINE_3D:
1675 error = dwg_dxfb_POLYLINE_3D (dat, obj);
1676 return error | dxfb_process_VERTEX_3D (dat, obj, i);
1677 case DWG_TYPE_POLYLINE_PFACE:
1678 error = dwg_dxfb_POLYLINE_PFACE (dat, obj);
1679 return error | dxfb_process_VERTEX_PFACE (dat, obj, i);
1680 case DWG_TYPE_POLYLINE_MESH:
1681 error = dwg_dxfb_POLYLINE_MESH (dat, obj);
1682 return error | dxfb_process_VERTEX_MESH (dat, obj, i);
1683
1684 case DWG_TYPE_ATTRIB:
1685 LOG_WARN ("stale %s subentity", obj->dxfname);
1686 return dwg_dxfb_ATTRIB (dat, obj);
1687 case DWG_TYPE_VERTEX_2D:
1688 LOG_WARN ("stale %s subentity", obj->dxfname);
1689 return dwg_dxfb_VERTEX_2D (dat, obj);
1690 case DWG_TYPE_VERTEX_3D:
1691 LOG_WARN ("stale %s subentity", obj->dxfname);
1692 return dwg_dxfb_VERTEX_3D (dat, obj);
1693 case DWG_TYPE_VERTEX_MESH:
1694 LOG_WARN ("stale %s subentity", obj->dxfname);
1695 return dwg_dxfb_VERTEX_MESH (dat, obj);
1696 case DWG_TYPE_VERTEX_PFACE:
1697 LOG_WARN ("stale %s subentity", obj->dxfname);
1698 return dwg_dxfb_VERTEX_PFACE (dat, obj);
1699 case DWG_TYPE_VERTEX_PFACE_FACE:
1700 LOG_WARN ("stale %s subentity", obj->dxfname);
1701 return dwg_dxfb_VERTEX_PFACE_FACE (dat, obj);
1702
1703 case DWG_TYPE_ARC:
1704 return dwg_dxfb_ARC (dat, obj);
1705 case DWG_TYPE_CIRCLE:
1706 return dwg_dxfb_CIRCLE (dat, obj);
1707 case DWG_TYPE_LINE:
1708 return dwg_dxfb_LINE (dat, obj);
1709 case DWG_TYPE_DIMENSION_ORDINATE:
1710 return dwg_dxfb_DIMENSION_ORDINATE (dat, obj);
1711 case DWG_TYPE_DIMENSION_LINEAR:
1712 return dwg_dxfb_DIMENSION_LINEAR (dat, obj);
1713 case DWG_TYPE_DIMENSION_ALIGNED:
1714 return dwg_dxfb_DIMENSION_ALIGNED (dat, obj);
1715 case DWG_TYPE_DIMENSION_ANG3PT:
1716 return dwg_dxfb_DIMENSION_ANG3PT (dat, obj);
1717 case DWG_TYPE_DIMENSION_ANG2LN:
1718 return dwg_dxfb_DIMENSION_ANG2LN (dat, obj);
1719 case DWG_TYPE_DIMENSION_RADIUS:
1720 return dwg_dxfb_DIMENSION_RADIUS (dat, obj);
1721 case DWG_TYPE_DIMENSION_DIAMETER:
1722 return dwg_dxfb_DIMENSION_DIAMETER (dat, obj);
1723 case DWG_TYPE_POINT:
1724 return dwg_dxfb_POINT (dat, obj);
1725 case DWG_TYPE__3DFACE:
1726 return dwg_dxfb__3DFACE (dat, obj);
1727 case DWG_TYPE_SOLID:
1728 return dwg_dxfb_SOLID (dat, obj);
1729 case DWG_TYPE_TRACE:
1730 return dwg_dxfb_TRACE (dat, obj);
1731 case DWG_TYPE_SHAPE:
1732 return dwg_dxfb_SHAPE (dat, obj);
1733 case DWG_TYPE_VIEWPORT:
1734 return minimal ? 0 : dwg_dxfb_VIEWPORT (dat, obj);
1735 case DWG_TYPE_ELLIPSE:
1736 return dwg_dxfb_ELLIPSE (dat, obj);
1737 case DWG_TYPE_SPLINE:
1738 return dwg_dxfb_SPLINE (dat, obj);
1739 case DWG_TYPE_REGION:
1740 return dwg_dxfb_REGION (dat, obj);
1741 case DWG_TYPE__3DSOLID:
1742 return dwg_dxfb__3DSOLID (dat, obj);
1743 case DWG_TYPE_BODY:
1744 return dwg_dxfb_BODY (dat, obj);
1745 case DWG_TYPE_RAY:
1746 return dwg_dxfb_RAY (dat, obj);
1747 case DWG_TYPE_XLINE:
1748 return dwg_dxfb_XLINE (dat, obj);
1749 case DWG_TYPE_DICTIONARY:
1750 return minimal ? 0 : dwg_dxfb_DICTIONARY (dat, obj);
1751 case DWG_TYPE_MTEXT:
1752 return dwg_dxfb_MTEXT (dat, obj);
1753 case DWG_TYPE_LEADER:
1754 return dwg_dxfb_LEADER (dat, obj);
1755 case DWG_TYPE_TOLERANCE:
1756 return dwg_dxfb_TOLERANCE (dat, obj);
1757 case DWG_TYPE_MLINE:
1758 if (0)
1759 {
1760 // bypass -Wunused-function
1761 dwg_dxfb_JUMP (dat, obj);
1762 dwg_dxfb_LOAD (dat, obj);
1763 }
1764 #ifdef DEBUG_CLASSES
1765 // TODO: looks good, but acad import crashes
1766 return dwg_dxfb_MLINE (dat, obj);
1767 #else
1768 LOG_WARN ("Unhandled Entity MLINE in out_dxfb %u/" FMT_H, obj->index,
1769 obj->handle.value)
1770 if (0)
1771 // bypass -Wunused-function
1772 dwg_dxfb_MLINE (dat, obj);
1773 return DWG_ERR_UNHANDLEDCLASS;
1774 #endif
1775 case DWG_TYPE_BLOCK_CONTROL:
1776 case DWG_TYPE_BLOCK_HEADER:
1777 case DWG_TYPE_LAYER_CONTROL:
1778 case DWG_TYPE_LAYER:
1779 case DWG_TYPE_STYLE_CONTROL:
1780 case DWG_TYPE_STYLE:
1781 case DWG_TYPE_LTYPE_CONTROL:
1782 case DWG_TYPE_LTYPE:
1783 case DWG_TYPE_VIEW_CONTROL:
1784 case DWG_TYPE_VIEW:
1785 case DWG_TYPE_UCS_CONTROL:
1786 case DWG_TYPE_UCS:
1787 case DWG_TYPE_VPORT_CONTROL:
1788 case DWG_TYPE_VPORT:
1789 case DWG_TYPE_APPID_CONTROL:
1790 case DWG_TYPE_APPID:
1791 case DWG_TYPE_DIMSTYLE_CONTROL:
1792 case DWG_TYPE_DIMSTYLE:
1793 case DWG_TYPE_VX_CONTROL:
1794 /* no dxf */
1795 case DWG_TYPE_VX_TABLE_RECORD:
1796 /* preR13: no dxfb */
1797 case DWG_TYPE_REPEAT:
1798 case DWG_TYPE_ENDREP:
1799 case DWG_TYPE__3DLINE:
1800 case DWG_TYPE_LOAD:
1801 case DWG_TYPE_JUMP:
1802 LOG_INFO ("Skip unsupported object %s\n", obj->name);
1803 break;
1804
1805 case DWG_TYPE_GROUP:
1806 return dwg_dxfb_GROUP (dat, obj);
1807 case DWG_TYPE_MLINESTYLE:
1808 return minimal ? 0 : dwg_dxfb_MLINESTYLE (dat, obj);
1809 case DWG_TYPE_OLE2FRAME:
1810 return minimal ? 0 : dwg_dxfb_OLE2FRAME (dat, obj);
1811 case DWG_TYPE_DUMMY:
1812 return 0;
1813 case DWG_TYPE_LONG_TRANSACTION:
1814 return minimal ? 0 : dwg_dxfb_LONG_TRANSACTION (dat, obj);
1815 case DWG_TYPE_LWPOLYLINE:
1816 return dwg_dxfb_LWPOLYLINE (dat, obj);
1817 case DWG_TYPE_HATCH:
1818 return dwg_dxfb_HATCH (dat, obj);
1819 case DWG_TYPE_XRECORD:
1820 return minimal ? 0 : dwg_dxfb_XRECORD (dat, obj);
1821 case DWG_TYPE_PLACEHOLDER:
1822 return minimal ? 0 : dwg_dxfb_PLACEHOLDER (dat, obj);
1823 case DWG_TYPE_PROXY_ENTITY:
1824 return minimal ? 0 : dwg_dxfb_PROXY_ENTITY (dat, obj);
1825 case DWG_TYPE_OLEFRAME:
1826 return minimal ? 0 : dwg_dxfb_OLEFRAME (dat, obj);
1827 case DWG_TYPE_VBA_PROJECT:
1828 if (!minimal)
1829 {
1830 LOG_ERROR ("Unhandled Object VBA_PROJECT");
1831 // dwg_dxfb_VBA_PROJECT(dat, obj);
1832 return DWG_ERR_UNHANDLEDCLASS;
1833 }
1834 return 0;
1835 case DWG_TYPE_LAYOUT:
1836 return minimal ? 0 : dwg_dxfb_LAYOUT (dat, obj);
1837 default:
1838 if (obj->type == obj->parent->layout_type)
1839 {
1840 return minimal ? 0 : dwg_dxfb_LAYOUT (dat, obj);
1841 }
1842 /* > 500 */
1843 else if (DWG_ERR_UNHANDLEDCLASS
1844 & (error = dwg_dxfb_variable_type (obj->parent, dat,
1845 (Dwg_Object *)obj)))
1846 {
1847 Dwg_Data *dwg = obj->parent;
1848 int j = obj->type - 500;
1849 Dwg_Class *klass = NULL;
1850
1851 if (j >= 0 && j < (int)dwg->num_classes
1852 && obj->fixedtype < DWG_TYPE_FREED)
1853 klass = &dwg->dwg_class[j];
1854 if (!klass)
1855 {
1856 LOG_WARN ("Unknown object, skipping eed/reactors/xdic");
1857 return DWG_ERR_INVALIDTYPE;
1858 }
1859 return error;
1860 }
1861 }
1862 return DWG_ERR_UNHANDLEDCLASS;
1863 }
1864
1865 static int
1866 dxfb_common_entity_handle_data (Bit_Chain *restrict dat,
1867 const Dwg_Object *restrict obj)
1868 {
1869 const Dwg_Data *dwg = obj->parent;
1870 const Dwg_Object_Entity *_ent = obj->tio.entity;
1871 const Dwg_Object_Entity *_obj = _ent;
1872 int error = 0;
1873 BITCODE_BL vcount = 0;
1874
1875 // clang-format off
1876 if (dat->version >= R_13b1)
1877 {
1878 #include "common_entity_handle_data.spec"
1879 }
1880 #include "common_entity_data.spec"
1881 // clang-format on
1882
1883 return error;
1884 }
1885
1886 // see
1887 // https://www.autodesk.com/techpubs/autocad/acad2000/dxf/header_section_group_codes_dxf_02.htm
1888 AFL_GCC_TOOBIG
1889 static int
1890 dxfb_header_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1891 {
1892 Dwg_Header_Variables *_obj = &dwg->header_vars;
1893 Dwg_Object *obj = NULL;
1894 double ms;
1895 const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
1896 const char *codepage = dxf_codepage (dwg->header.codepage, dwg);
1897
1898 if (dwg->header.codepage != 30 && dwg->header.codepage != 29
1899 && dwg->header.codepage != 0 && dwg->header.version < R_2007)
1900 {
1901 // some asian or eastern-european codepage
1902 // see
1903 // https://github.com/mozman/ezdxf/blob/master/docs/source/dxfinternals/fileencoding.rst
1904 LOG_WARN ("Unknown codepage %d, assuming ANSI_1252",
1905 dwg->header.codepage);
1906 }
1907
1908 // clang-format off
1909 #include "header_variables_dxf.spec"
1910 // clang-format on
1911
1912 return 0;
1913 }
1914 AFL_GCC_POP
1915
1916 static int
1917 dxfb_classes_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1918 {
1919 BITCODE_BS j;
1920
1921 SECTION (CLASSES);
1922 LOG_TRACE ("num_classes: %u\n", dwg->num_classes);
1923 for (j = 0; j < dwg->num_classes; j++)
1924 {
1925 const char *dxfname = dwg->dwg_class[j].dxfname;
1926 if (!dxfname)
1927 continue;
1928 // some classes are now builtin
1929 if (dat->version >= R_2004
1930 && (strEQc (dxfname, "ACDBPLACEHOLDER")
1931 || strEQc (dxfname, "LAYOUT")))
1932 continue;
1933 if (strEQc (dxfname, "DATATABLE"))
1934 dxfname = "ACDBDATATABLE";
1935 RECORD (CLASS);
1936 VALUE_TV (dxfname, 1);
1937 VALUE_T (dwg->dwg_class[j].cppname, 2);
1938 if (strEQc (dxfname, "SPATIAL_INDEX"))
1939 VALUE_TFF ("AutoCAD 2000", 3)
1940 else
1941 VALUE_T (dwg->dwg_class[j].appname, 3)
1942 VALUE_RL (dwg->dwg_class[j].proxyflag, 90);
1943 SINCE (R_2004)
1944 {
1945 VALUE_RL (dwg->dwg_class[j].num_instances, 91);
1946 }
1947 VALUE_RS (dwg->dwg_class[j].is_zombie, 280); // acad: was-a-zombie
1948 // Is-an-entity. 1f2 for entities, 1f3 for objects
1949 VALUE_RS (dwg->dwg_class[j].item_class_id == 0x1F2 ? 1 : 0, 281);
1950 }
1951 ENDSEC ();
1952 return 0;
1953 }
1954
1955 static int
1956 dxfb_tables_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1957 {
1958 int error = 0;
1959 unsigned int i;
1960
1961 SECTION (TABLES);
1962 SINCE (R_9c1)
1963 {
1964 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_VPORT_CONTROL);
1965 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.VPORT_CONTROL)
1966 {
1967 Dwg_Object *obj = ctrl;
1968 Dwg_Object_VPORT_CONTROL *_ctrl = ctrl->tio.object->tio.VPORT_CONTROL;
1969 TABLE (VPORT);
1970 // add handle 5 here at first
1971 COMMON_TABLE_CONTROL_FLAGS;
1972 error |= dwg_dxfb_VPORT_CONTROL (dat, ctrl);
1973 // TODO how far back can DXF read 1000?
1974 if (dat->version != dat->from_version && dat->from_version >= R_2000)
1975 {
1976 /* if saved from newer version, eg. AC1032: */
1977 VALUE_TV ("ACAD", 1001);
1978 VALUE_TV ("DbSaveVer", 1000);
1979 VALUE_RS (dwg->header.dwg_version, 1071); // so that 69 is R_2018
1980 }
1981 for (i = 0; i < _ctrl->num_entries; i++)
1982 {
1983 if (!_ctrl->entries)
1984 break;
1985 if (!_ctrl->entries[i])
1986 continue;
1987 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
1988 if (obj && obj->type == DWG_TYPE_VPORT)
1989 {
1990 // reordered in the DXF: 2,70,10,11,12,13,14,15,16,...
1991 // special-cased in the spec
1992 error |= dwg_dxfb_VPORT (dat, obj);
1993 }
1994 }
1995 ENDTAB ();
1996 }
1997 }
1998 {
1999 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_LTYPE_CONTROL);
2000 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.LTYPE_CONTROL)
2001 {
2002 Dwg_Object *obj = ctrl;
2003 Dwg_Object_LTYPE_CONTROL *_ctrl = ctrl->tio.object->tio.LTYPE_CONTROL;
2004 TABLE (LTYPE);
2005 COMMON_TABLE_CONTROL_FLAGS;
2006 error |= dwg_dxfb_LTYPE_CONTROL (dat, ctrl);
2007 // first the 2 builtin ltypes: ByBlock, ByLayer
2008 if ((obj = dwg_ref_object (dwg, dwg->header_vars.LTYPE_BYBLOCK)))
2009 {
2010 dwg_dxfb_LTYPE (dat, obj);
2011 }
2012 if ((obj = dwg_ref_object (dwg, dwg->header_vars.LTYPE_BYLAYER)))
2013 {
2014 error |= dwg_dxfb_LTYPE (dat, obj);
2015 }
2016 // here LTYPE_CONTINUOUS is already included
2017 for (i = 0; i < _ctrl->num_entries; i++)
2018 {
2019 if (!_ctrl->entries)
2020 break;
2021 if (!_ctrl->entries[i])
2022 continue;
2023 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2024 if (obj && obj->type == DWG_TYPE_LTYPE)
2025 {
2026 error |= dwg_dxfb_LTYPE (dat, obj);
2027 }
2028 }
2029 ENDTAB ();
2030 }
2031 }
2032 {
2033 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_LAYER_CONTROL);
2034 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.LAYER_CONTROL)
2035 {
2036 Dwg_Object *obj = ctrl;
2037 Dwg_Object_LAYER_CONTROL *_ctrl = ctrl->tio.object->tio.LAYER_CONTROL;
2038 TABLE (LAYER);
2039 COMMON_TABLE_CONTROL_FLAGS;
2040 error |= dwg_dxfb_LAYER_CONTROL (dat, ctrl);
2041 for (i = 0; i < _ctrl->num_entries; i++)
2042 {
2043 if (!_ctrl->entries)
2044 break;
2045 if (!_ctrl->entries[i])
2046 continue;
2047 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2048 if (obj && obj->type == DWG_TYPE_LAYER)
2049 {
2050 error |= dwg_dxfb_LAYER (dat, obj);
2051 // else if (obj && obj->type == DWG_TYPE_DICTIONARY)
2052 // error |= dwg_dxfb_DICTIONARY(dat, obj);
2053 }
2054 }
2055 ENDTAB ();
2056 }
2057 }
2058 {
2059 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_STYLE_CONTROL);
2060 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.STYLE_CONTROL)
2061 {
2062 Dwg_Object *obj = ctrl;
2063 Dwg_Object_STYLE_CONTROL *_ctrl = ctrl->tio.object->tio.STYLE_CONTROL;
2064 TABLE (STYLE);
2065 COMMON_TABLE_CONTROL_FLAGS;
2066 error |= dwg_dxfb_STYLE_CONTROL (dat, ctrl);
2067 for (i = 0; i < _ctrl->num_entries; i++)
2068 {
2069 if (!_ctrl->entries)
2070 break;
2071 if (!_ctrl->entries[i])
2072 continue;
2073 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2074 if (obj && obj->type == DWG_TYPE_STYLE)
2075 {
2076 error |= dwg_dxfb_STYLE (dat, obj);
2077 }
2078 }
2079 ENDTAB ();
2080 }
2081 }
2082 {
2083 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_VIEW_CONTROL);
2084 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.VIEW_CONTROL)
2085 {
2086 Dwg_Object *obj = ctrl;
2087 Dwg_Object_VIEW_CONTROL *_ctrl = ctrl->tio.object->tio.VIEW_CONTROL;
2088 TABLE (VIEW);
2089 COMMON_TABLE_CONTROL_FLAGS;
2090 error |= dwg_dxfb_VIEW_CONTROL (dat, ctrl);
2091 for (i = 0; i < _ctrl->num_entries; i++)
2092 {
2093 if (!_ctrl->entries)
2094 break;
2095 if (!_ctrl->entries[i])
2096 continue;
2097 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2098 if (obj && obj->type == DWG_TYPE_VIEW)
2099 error |= dwg_dxfb_VIEW (dat, obj);
2100 }
2101 ENDTAB ();
2102 }
2103 }
2104 SINCE (R_9c1)
2105 {
2106 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_UCS_CONTROL);
2107 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.UCS_CONTROL)
2108 {
2109 Dwg_Object *obj = ctrl;
2110 Dwg_Object_UCS_CONTROL *_ctrl = ctrl->tio.object->tio.UCS_CONTROL;
2111 TABLE (UCS);
2112 COMMON_TABLE_CONTROL_FLAGS;
2113 error |= dwg_dxfb_UCS_CONTROL (dat, ctrl);
2114 for (i = 0; i < _ctrl->num_entries; i++)
2115 {
2116 if (!_ctrl->entries)
2117 break;
2118 if (!_ctrl->entries[i])
2119 continue;
2120 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2121 if (obj && obj->type == DWG_TYPE_UCS)
2122 {
2123 error |= dwg_dxfb_UCS (dat, obj);
2124 }
2125 }
2126 ENDTAB ();
2127 }
2128 }
2129 SINCE (R_11b1)
2130 {
2131 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_APPID_CONTROL);
2132 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.APPID_CONTROL)
2133 {
2134 Dwg_Object *obj = ctrl;
2135 Dwg_Object_APPID_CONTROL *_ctrl = ctrl->tio.object->tio.APPID_CONTROL;
2136 TABLE (APPID);
2137 COMMON_TABLE_CONTROL_FLAGS;
2138 error |= dwg_dxfb_APPID_CONTROL (dat, ctrl);
2139 for (i = 0; i < _ctrl->num_entries; i++)
2140 {
2141 if (!_ctrl->entries)
2142 break;
2143 if (!_ctrl->entries[i])
2144 continue;
2145 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2146 if (obj && obj->type == DWG_TYPE_APPID)
2147 {
2148 error |= dwg_dxfb_APPID (dat, obj);
2149 }
2150 }
2151 ENDTAB ();
2152 }
2153 }
2154 SINCE (R_11b1)
2155 {
2156 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_DIMSTYLE_CONTROL);
2157 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.DIMSTYLE_CONTROL)
2158 {
2159 Dwg_Object *obj = ctrl;
2160 Dwg_Object_DIMSTYLE_CONTROL *_ctrl
2161 = ctrl->tio.object->tio.DIMSTYLE_CONTROL;
2162 TABLE (DIMSTYLE);
2163 COMMON_TABLE_CONTROL_FLAGS;
2164 dwg_dxfb_DIMSTYLE_CONTROL (dat, ctrl);
2165 // ignoring morehandles
2166 for (i = 0; i < _ctrl->num_entries; i++)
2167 {
2168 if (!_ctrl->entries)
2169 break;
2170 if (!_ctrl->entries[i])
2171 continue;
2172 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2173 if (obj && obj->type == DWG_TYPE_DIMSTYLE)
2174 {
2175 error |= dwg_dxfb_DIMSTYLE (dat, obj);
2176 }
2177 }
2178 ENDTAB ();
2179 }
2180 }
2181 // fool the warnings. this table is nowhere to be found in the wild. maybe
2182 // pre-R11
2183 if (0)
2184 {
2185 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_VX_CONTROL);
2186 Dwg_Object_VX_CONTROL *_ctrl = ctrl->tio.object->tio.VX_CONTROL;
2187 if (ctrl && ctrl->fixedtype == DWG_TYPE_VX_CONTROL)
2188 {
2189 Dwg_Object *obj = ctrl;
2190 TABLE (VX_TABLE_RECORD);
2191 COMMON_TABLE_CONTROL_FLAGS;
2192 error |= dwg_dxfb_VX_CONTROL (dat, ctrl);
2193 for (i = 0; i < _ctrl->num_entries; i++)
2194 {
2195 if (!_ctrl->entries)
2196 break;
2197 if (!_ctrl->entries[i])
2198 continue;
2199 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2200 if (obj && obj->type == DWG_TYPE_VX_TABLE_RECORD)
2201 {
2202 RECORD (VX_TABLE_RECORD);
2203 error |= dwg_dxfb_VX_TABLE_RECORD (dat, obj);
2204 }
2205 }
2206 ENDTAB ();
2207 }
2208 }
2209 SINCE (R_12)
2210 {
2211 Dwg_Object *ctrl, *obj;
2212 Dwg_Object_BLOCK_CONTROL *_ctrl = dwg_block_control (dwg);
2213 Dwg_Object_Ref *ref;
2214 Dwg_Object *mspace = NULL, *pspace = NULL;
2215 if (!_ctrl)
2216 {
2217 LOG_ERROR ("BLOCK_CONTROL missing");
2218 return DWG_ERR_INVALIDDWG;
2219 }
2220 ctrl = dwg_obj_generic_to_object (_ctrl, &error);
2221 if (!ctrl || ctrl->fixedtype != DWG_TYPE_BLOCK_CONTROL)
2222 return DWG_ERR_INVALIDDWG;
2223
2224 obj = ctrl;
2225 TABLE (BLOCK_RECORD);
2226 COMMON_TABLE_CONTROL_FLAGS;
2227 error |= dwg_dxfb_BLOCK_CONTROL (dat, ctrl);
2228
2229 #if 0
2230 for (i = 0; i < dwg->num_objects; i++)
2231 {
2232 Dwg_Object *hdr = &dwg->object[i];
2233 if (hdr && hdr->supertype == DWG_SUPERTYPE_OBJECT
2234 && hdr->type == DWG_TYPE_BLOCK_HEADER)
2235 {
2236 RECORD (BLOCK_RECORD);
2237 error |= dwg_dxfb_BLOCK_HEADER (dat, hdr);
2238 }
2239 }
2240 #else
2241 mspace = dwg_model_space_object (dwg);
2242 if (!mspace)
2243 return DWG_ERR_INVALIDDWG;
2244 RECORD (BLOCK_RECORD);
2245 error |= dwg_dxfb_BLOCK_HEADER (dat, mspace);
2246
2247 ref = dwg_paper_space_ref (dwg);
2248 pspace = ref ? dwg_ref_object (dwg, ref) : NULL;
2249 if (pspace)
2250 {
2251 RECORD (BLOCK_RECORD);
2252 error |= dwg_dxfb_BLOCK_HEADER (dat, pspace);
2253 }
2254
2255 for (i = 0; i < _ctrl->num_entries; i++)
2256 {
2257 if (!_ctrl->entries)
2258 break;
2259 if (!_ctrl->entries[i])
2260 continue;
2261 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
2262 if (obj && obj->type == DWG_TYPE_BLOCK_HEADER && obj != mspace
2263 && obj != pspace)
2264 {
2265 RECORD (BLOCK_RECORD);
2266 error |= dwg_dxfb_BLOCK_HEADER (dat, obj);
2267 }
2268 }
2269 #endif
2270
2271 ENDTAB ();
2272 }
2273
2274 ENDSEC ();
2275 return 0;
2276 }
2277
2278 static void
2279 dxfb_ENDBLK_empty (Bit_Chain *restrict dat, const Dwg_Object *restrict hdr)
2280 {
2281 Dwg_Object *obj = (Dwg_Object *)calloc (1, sizeof (Dwg_Object));
2282 obj->parent = hdr->parent;
2283 obj->index = obj->parent->num_objects;
2284 dwg_setup_ENDBLK (obj);
2285 obj->tio.entity->ownerhandle
2286 = (Dwg_Object_Ref *)calloc (1, sizeof (Dwg_Object_Ref));
2287 obj->tio.entity->ownerhandle->obj = (Dwg_Object *)hdr;
2288 obj->tio.entity->ownerhandle->handleref = hdr->handle;
2289 obj->tio.entity->ownerhandle->absolute_ref = hdr->handle.value;
2290 dwg_dxfb_ENDBLK (dat, obj);
2291 free (obj->tio.entity->tio.ENDBLK);
2292 free (obj->tio.entity->ownerhandle);
2293 free (obj->tio.entity);
2294 free (obj);
2295 }
2296
2297 static int
2298 dxfb_block_write (Bit_Chain *restrict dat, const Dwg_Object *restrict hdr,
2299 const Dwg_Object *restrict mspace,
2300 const Dwg_Object *restrict pspace, int *restrict i)
2301 {
2302 int error = 0;
2303 Dwg_Object *restrict obj = get_first_owned_block (hdr); // BLOCK
2304 const Dwg_Object_BLOCK_HEADER *restrict _hdr
2305 = hdr->tio.object->tio.BLOCK_HEADER;
2306 Dwg_Object *restrict endblk;
2307 Dwg_Data *dwg = hdr->parent;
2308 BITCODE_RLL mspace_ref = mspace ? mspace->handle.value : 0;
2309 BITCODE_RLL pspace_ref = pspace ? pspace->handle.value : 0;
2310
2311 if (obj)
2312 error |= dwg_dxfb_object (dat, obj, i);
2313 else
2314 {
2315 LOG_ERROR ("BLOCK_HEADER.block_entity missing");
2316 return DWG_ERR_INVALIDDWG;
2317 }
2318 // Skip all *Model_Space and *Paper_Space entities, esp. new ones: UNDERLAY,
2319 // MULTILEADER, ... They are all under ENTITIES later. Note: the objects may
2320 // vary (e.g. example_2000), but the index not
2321 if ((hdr == mspace) || (hdr->index == mspace->index))
2322 obj = NULL;
2323 else if ((hdr == pspace) || (pspace && hdr->index == pspace->index))
2324 obj = NULL;
2325 else
2326 obj = get_first_owned_entity (hdr); // first_entity
2327 while (obj)
2328 {
2329 if (obj->supertype == DWG_SUPERTYPE_ENTITY
2330 && obj->fixedtype != DWG_TYPE_ENDBLK && obj->tio.entity != NULL
2331 && (obj->tio.entity->entmode != 2
2332 || (obj->tio.entity->ownerhandle != NULL
2333 && obj->tio.entity->ownerhandle->absolute_ref != mspace_ref
2334 && obj->tio.entity->ownerhandle->absolute_ref
2335 != pspace_ref)))
2336 error |= dwg_dxfb_object (dat, obj, i);
2337 obj = get_next_owned_entity (hdr, obj); // until last_entity
2338 }
2339 endblk = get_last_owned_block (hdr);
2340 if (endblk)
2341 error |= dwg_dxfb_ENDBLK (dat, endblk);
2342 else
2343 {
2344 LOG_WARN ("Empty ENDBLK for \"%s\" " FORMAT_BL, _hdr->name,
2345 hdr ? hdr->tio.object->objid : 0);
2346 dxfb_ENDBLK_empty (dat, hdr);
2347 }
2348 return error;
2349 }
2350
2351 static int
2352 dxfb_blocks_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2353 {
2354 int error = 0;
2355 int i = 0;
2356 Dwg_Object *restrict mspace = dwg_model_space_object (dwg);
2357 Dwg_Object *restrict pspace = dwg_paper_space_object (dwg);
2358
2359 if (!mspace)
2360 return DWG_ERR_UNHANDLEDCLASS;
2361
2362 SECTION (BLOCKS);
2363 /* There may be unconnected blocks (not caught by above),
2364 such as pspace referred by a LAYOUT or DIMENSION, so for simplicity just
2365 scan all BLOCK_HEADER's and just skip *Model_Space and *Paper_Space.
2366 pspace might be NULL.
2367 */
2368 {
2369 for (i = 0; (BITCODE_BL)i < dwg->num_objects; i++)
2370 {
2371 const Dwg_Object *restrict obj = &dwg->object[i];
2372 if (obj->supertype == DWG_SUPERTYPE_OBJECT
2373 && obj->type == DWG_TYPE_BLOCK_HEADER)
2374 {
2375 error |= dxfb_block_write (dat, obj, mspace, pspace, &i);
2376 }
2377 }
2378 }
2379
2380 ENDSEC ();
2381 return error;
2382 }
2383
2384 static int
2385 dxfb_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2386 {
2387 int error = 0;
2388 Dwg_Object *restrict ms = dwg_model_space_object (dwg);
2389 Dwg_Object *restrict ps = dwg_paper_space_object (dwg);
2390 Dwg_Object *obj;
2391 if (!ms)
2392 return DWG_ERR_INVALIDDWG;
2393
2394 SECTION (ENTITIES);
2395 // First mspace
2396 obj = get_first_owned_entity (ms); // first_entity or entities[0]
2397 while (obj)
2398 {
2399 int i = obj->index;
2400 error |= dwg_dxfb_object (dat, obj, &i);
2401 obj = get_next_owned_block_entity (ms, obj); // until last_entity
2402 }
2403 // Then all pspace entities. just filter out other BLOCKS entities
2404 if (ps)
2405 {
2406 obj = get_first_owned_entity (ps);
2407 while (obj)
2408 {
2409 int i = obj->index;
2410 error |= dwg_dxfb_object (dat, obj, &i);
2411 obj = get_next_owned_block_entity (ps, obj);
2412 }
2413 }
2414 ENDSEC ();
2415 return error;
2416 }
2417
2418 static int
2419 dxfb_objects_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2420 {
2421 int error = 0;
2422 int i = 0;
2423 Dwg_Object *nod;
2424
2425 SECTION (OBJECTS);
2426 // The NOD (Named Object Dict) must be always the very first OBJECT,
2427 // not just DICTIONARY.
2428 nod = dwg_get_first_object (dwg, DWG_TYPE_DICTIONARY);
2429 if (nod)
2430 error |= dwg_dxfb_object (dat, nod, &i);
2431 for (i = 0; (BITCODE_BL)i < dwg->num_objects; i++)
2432 {
2433 const Dwg_Object *restrict obj = &dwg->object[i];
2434 if (obj == nod)
2435 continue;
2436 if (obj->supertype == DWG_SUPERTYPE_OBJECT
2437 && obj->type != DWG_TYPE_BLOCK_HEADER && !dwg_obj_is_control (obj))
2438 error |= dwg_dxfb_object (dat, obj, &i);
2439 }
2440 ENDSEC ();
2441 return error;
2442 }
2443
2444 static int
2445 dxfb_thumbnail_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2446 {
2447 Bit_Chain *pic = (Bit_Chain *)&dwg->thumbnail;
2448 if (pic->chain && pic->size && pic->size > 10)
2449 {
2450 SECTION (THUMBNAILIMAGE);
2451 VALUE_RL (pic->size, 90);
2452 VALUE_BINARY (pic->chain, pic->size, 310);
2453 ENDSEC ();
2454 }
2455 return 0;
2456 }
2457
2458 int
2459 dwg_write_dxfb (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2460 {
2461 int error = 0;
2462 const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
2463
2464 loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
2465 if (dat->from_version == R_INVALID)
2466 dat->from_version = dat->version;
2467 if (dwg->header.version <= R_2000 && dwg->header.from_version > R_2000)
2468 dwg_fixup_BLOCKS_entities (dwg);
2469 dwg_resolve_objectrefs_silent (dwg);
2470
2471 fprintf (dat->fh, "AutoCAD Binary DXF\r\n%c%c", 0x1a, 0);
2472 // VALUE_TV (PACKAGE_STRING, 999); // not used in binary DXF
2473
2474 // a minimal header requires only $ACADVER, $HANDSEED, and then ENTITIES
2475 // see https://pythonhosted.org/ezdxf/dxfinternals/filestructure.html
2476 dxfb_header_write (dat, dwg);
2477
2478 if (!minimal)
2479 {
2480 // if downgraded to r13, but we still have classes, keep the
2481 // classes
2482 if ((dat->from_version >= R_13b1 && dwg->num_classes)
2483 || dat->version >= R_2000)
2484 {
2485 if (dxfb_classes_write (dat, dwg) >= DWG_ERR_CRITICAL)
2486 goto fail;
2487 }
2488
2489 if (dxfb_tables_write (dat, dwg) >= DWG_ERR_CRITICAL)
2490 goto fail;
2491
2492 if (dxfb_blocks_write (dat, dwg) >= DWG_ERR_CRITICAL)
2493 goto fail;
2494 }
2495
2496 if (dxfb_entities_write (dat, dwg) >= DWG_ERR_CRITICAL)
2497 goto fail;
2498
2499 if (!minimal)
2500 {
2501 SINCE (R_13b1)
2502 {
2503 if (dxfb_objects_write (dat, dwg) >= DWG_ERR_CRITICAL)
2504 goto fail;
2505 }
2506 SINCE (R_2000)
2507 {
2508 if (dxfb_thumbnail_write (dat, dwg) >= DWG_ERR_CRITICAL)
2509 goto fail;
2510 }
2511 }
2512 RECORD (EOF);
2513
2514 return 0;
2515 fail:
2516 return 1;
2517 }
2518
2519 #undef IS_PRINT
2520 #undef IS_DXF