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_dxf.c: write as Ascii DXF
15 * written by Reini Urban
16 */
17
18 /* Works mostly.
19 TODO:
20 * down-conversions from unsupported entities on older DXF versions.
21 Since r13:
22 Entities: LWPOLYLINE, HATCH, SPLINE, LEADER, DIMENSION, MTEXT, IMAGE,
23 BLOCK_RECORD. Add CLASSES for those.
24 */
25
26 #include "config.h"
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <assert.h>
31 //#include <math.h>
32
33 #define IS_DXF
34 #include "common.h"
35 #include "bits.h"
36 #include "myalloca.h"
37 #include "dwg.h"
38 #include "decode.h"
39 #include "encode.h"
40 #include "out_dxf.h"
41
42 static unsigned int loglevel;
43 #define DWG_LOGLEVEL loglevel
44 #include "logging.h"
45
46 /* the current version per spec block */
47 static unsigned int cur_ver = 0;
48 static char buf[255];
49 static BITCODE_BL rcount1, rcount2;
50
51 // imported
52 char *dwg_obj_table_get_name (const Dwg_Object *restrict obj,
53 int *restrict error);
54 #ifndef _DWG_API_H_
55 Dwg_Object *dwg_obj_generic_to_object (const void *restrict obj,
56 int *restrict error);
57 #endif
58
59 // private
60 static int dxf_common_entity_handle_data (Bit_Chain *restrict dat,
61 const Dwg_Object *restrict obj);
62 static int dwg_dxf_object (Bit_Chain *restrict dat,
63 const Dwg_Object *restrict obj, int *restrict);
64 static int dxf_3dsolid (Bit_Chain *restrict dat,
65 const Dwg_Object *restrict obj,
66 Dwg_Entity_3DSOLID *restrict _obj);
67 static void dxf_fixup_string (Bit_Chain *restrict dat, char *restrict str,
68 const int opts, const int dxf, const int dxfcont);
69 static void dxf_CMC (Bit_Chain *restrict dat, Dwg_Color *restrict color,
70 const int dxf, const int opt);
71
72 /*--------------------------------------------------------------------------------
73 * MACROS
74 */
75
76 #define ACTION dxf
77
78 #define FIELD(nam, type) VALUE (_obj->nam, type, 0)
79 #define FIELDG(nam, type, dxf) VALUE (_obj->nam, type, dxf)
80 #define FIELD_CAST(nam, type, cast, dxf) FIELDG (nam, cast, dxf)
81 #define FIELD_TRACE(nam, type)
82 #define SUB_FIELD(o, nam, type, dxf) FIELDG (o.nam, type, dxf)
83 #define SUB_FIELD_CAST(o, nam, type, cast, dxf) FIELDG (o.nam, cast, dxf)
84
85 #define VALUE_TV(value, dxf) \
86 { \
87 GROUP (dxf); \
88 dxf_fixup_string (dat, (char *)value, 1, dxf, dxf); \
89 }
90 #define VALUE_TV0(value, dxf) \
91 if (dxf && value && *value) { \
92 GROUP (dxf); \
93 dxf_fixup_string (dat, (char *)value, 1, dxf, dxf); \
94 }
95 // in_json writes all strings as TV, in_dxf and decode not.
96 #define VALUE_TU(wstr, dxf) \
97 { \
98 if (dat->opts & DWG_OPTS_INJSON) \
99 { \
100 VALUE_TV (wstr, dxf); \
101 } \
102 else if (dxf) \
103 { \
104 char *u8 = bit_convert_TU ((BITCODE_TU)wstr); \
105 GROUP (dxf); \
106 if (u8) \
107 { \
108 dxf_fixup_string (dat, u8, 1, dxf, dxf); \
109 } \
110 else \
111 fprintf (dat->fh, "\r\n"); \
112 free (u8); \
113 } \
114 }
115 #define VALUE_TFF(str, dxf) \
116 { \
117 if (dxf) \
118 { \
119 GROUP (dxf); \
120 dxf_fixup_string (dat, (char *)str, 0, dxf, dxf); \
121 } \
122 }
123 #define VALUE_BINARY(value, size, dxf) \
124 { \
125 if (value && dxf) \
126 { \
127 for (unsigned long j = 0; j < (unsigned long)(size); j++) \
128 { \
129 if (!(j % 127)) \
130 { \
131 if (j) \
132 fprintf (dat->fh, "\r\n"); \
133 GROUP (dxf); \
134 } \
135 fprintf (dat->fh, "%02X", (value)[j]); \
136 } \
137 fprintf (dat->fh, "\r\n"); \
138 } \
139 }
140 #define FIELD_BINARY(name, size, dxf) \
141 if (dxf) \
142 VALUE_BINARY (_obj->name, size, dxf)
143
144 #define FIELD_VALUE(nam) _obj->nam
145 #define ANYCODE -1
146 // the hex code
147 #define VALUE_HANDLE(ref, nam, handle_code, dxf) \
148 if (dxf) \
149 { \
150 fprintf (dat->fh, "%3i\r\n%lX\r\n", dxf, \
151 ref ? ((BITCODE_H)ref)->absolute_ref : 0UL); \
152 }
153 // the name in the table, referenced by the handle
154 // names on: 6 7 8. which else? there are more styles: plot, ...
155 // rather skip unknown handles
156 #define FIELD_HANDLE(nam, handle_code, dxf) \
157 if (dxf != 0) \
158 { \
159 if (!_obj->nam) \
160 fprintf (dat->fh, "%3i\r\n%lX\r\n", dxf, 0UL); \
161 else if (dxf == 6) \
162 FIELD_HANDLE_NAME (nam, dxf, LTYPE) \
163 else if (dxf == 2) \
164 FIELD_HANDLE_NAME (nam, dxf, BLOCK_HEADER) \
165 else if (dxf == 3) \
166 FIELD_HANDLE_NAME (nam, dxf, DIMSTYLE) \
167 else if (dxf == 7) \
168 FIELD_HANDLE_NAME (nam, dxf, STYLE) \
169 else if (dxf == 8) \
170 FIELD_HANDLE_NAME (nam, dxf, LAYER) \
171 else if (dat->version >= R_13) \
172 fprintf (dat->fh, "%3i\r\n%lX\r\n", dxf, \
173 _obj->nam->obj ? _obj->nam->absolute_ref : 0UL); \
174 }
175 #define SUB_FIELD_HANDLE(o, nam, handle_code, dxf) \
176 if (dxf != 0) \
177 { \
178 if (!_obj->o.nam) \
179 fprintf (dat->fh, "%3i\r\n%lX\r\n", dxf, 0UL); \
180 else if (dxf == 6) \
181 SUB_FIELD_HANDLE_NAME (o, nam, dxf, LTYPE) \
182 else if (dxf == 3) \
183 SUB_FIELD_HANDLE_NAME (o, nam, dxf, DIMSTYLE) \
184 else if (dxf == 7) \
185 SUB_FIELD_HANDLE_NAME (o, nam, dxf, STYLE) \
186 else if (dxf == 8) \
187 SUB_FIELD_HANDLE_NAME (o, nam, dxf, LAYER) \
188 else if (dat->version >= R_13) \
189 fprintf (dat->fh, "%3i\r\n%lX\r\n", dxf, \
190 _obj->o.nam->obj ? _obj->o.nam->absolute_ref : 0UL); \
191 }
192 #define FIELD_HANDLE0(nam, handle_code, dxf) \
193 if (_obj->nam && _obj->nam->absolute_ref) \
194 { \
195 FIELD_HANDLE (nam, handle_code, dxf); \
196 }
197 #define SUB_FIELD_HANDLE0(o, nam, handle_code, dxf) \
198 if (_obj->o.nam && _obj->o.nam->absolute_ref) \
199 { \
200 SUB_FIELD_HANDLE (o, nam, handle_code, dxf); \
201 }
202 #define HEADER_9(nam) \
203 { \
204 GROUP (9); \
205 fprintf (dat->fh, "$%s\r\n", #nam); \
206 }
207 #define VALUE_H(value, dxf) \
208 if (dxf) \
209 fprintf (dat->fh, "%3i\r\n%lX\r\n", dxf, value)
210 #define HEADER_H(nam, dxf) \
211 { \
212 HEADER_9 (nam); \
213 VALUE_HANDLE (dwg->header_vars.nam, nam, 0, dxf); \
214 }
215 #define HEADER_H0(nam, dxf) \
216 if (dwg->header_vars.nam && dwg->header_vars.nam->absolute_ref) \
217 { \
218 HEADER_9 (nam); \
219 VALUE_H (dwg->header_vars.nam->absolute_ref, dxf); \
220 }
221 #define HEADER_VALUE(nam, type, dxf, value) \
222 if (dxf) \
223 { \
224 GROUP (9); \
225 fprintf (dat->fh, "$" #nam "\r\n"); \
226 VALUE (value, type, dxf); \
227 }
228 #define HEADER_VAR(nam, type, dxf) \
229 HEADER_VALUE (nam, type, dxf, dwg->header_vars.nam)
230 #define HEADER_VALUE_TV(nam, dxf, value) \
231 if (dxf) \
232 { \
233 GROUP (9); \
234 fprintf (dat->fh, "$" #nam "\r\n"); \
235 VALUE_TV (value, dxf); \
236 }
237 #define HEADER_VALUE_TU(nam, dxf, value) \
238 if (dxf) \
239 { \
240 GROUP (9); \
241 fprintf (dat->fh, "$" #nam "\r\n"); \
242 VALUE_TU (value, dxf); \
243 }
244 #define HEADER_VALUE_TU0(nam, dxf, value) \
245 if (dxf && !bit_empty_T (dat, (BITCODE_T)value)) \
246 { \
247 GROUP (9); \
248 fprintf (dat->fh, "$" #nam "\r\n"); \
249 VALUE_TU (value, dxf); \
250 }
251
252 #define HEADER_3D(nam) \
253 { \
254 HEADER_9 (nam); \
255 POINT_3D (nam, header_vars.nam, 10, 20, 30); \
256 }
257 #define HEADER_2D(nam) \
258 { \
259 HEADER_9 (nam); \
260 POINT_2D (nam, header_vars.nam, 10, 20); \
261 }
262 #define HEADER_BLL(nam, dxf) \
263 { \
264 HEADER_9 (nam); \
265 VALUE_BLL (dwg->header_vars.nam, dxf); \
266 }
267
268 #define SECTION(section) \
269 LOG_INFO ("\nSection " #section "\n") \
270 fprintf (dat->fh, " 0\r\nSECTION\r\n 2\r\n" #section "\r\n")
271 #define ENDSEC() fprintf (dat->fh, " 0\r\nENDSEC\r\n")
272 #define TABLE(table) fprintf (dat->fh, " 0\r\nTABLE\r\n 2\r\n" #table "\r\n")
273 #define ENDTAB() fprintf (dat->fh, " 0\r\nENDTAB\r\n")
274 #define RECORD(record) fprintf (dat->fh, " 0\r\n" #record "\r\n")
275 #define record(record) fprintf (dat->fh, " 0\r\n%s\r\n", record)
276 #define SUBCLASS(text) \
277 if (dat->version >= R_13) \
278 { \
279 VALUE_TV (#text, 100); \
280 }
281
282 #define GROUP(dxf) fprintf (dat->fh, "%3i\r\n", dxf)
283 /* avoid empty numbers, and fixup some bad %f GNU/BSD libc formatting */
284 #define VALUE(value, type, dxf) \
285 if (dxf) \
286 { \
287 const char *_fmt = dxf_format (dxf); \
288 assert (_fmt); \
289 if (strEQc (_fmt, DXF_FORMAT_FLT)) \
290 { \
291 dxf_print_rd (dat, (double)(value), dxf); \
292 } \
293 else \
294 { \
295 /* -Wpointer-to-int-cast */ \
296 const int32_t _si = (int32_t) (intptr_t) (value); \
297 GROUP (dxf); \
298 GCC46_DIAG_IGNORE (-Wformat-nonliteral) \
299 snprintf (buf, 255, _fmt, value); \
300 GCC46_DIAG_RESTORE \
301 /* not a string, empty num. must be zero */ \
302 if (strEQc (_fmt, "%s") && !*buf) \
303 fprintf (dat->fh, "0\r\n"); \
304 else if (90 <= dxf && dxf < 100) \
305 { \
306 fprintf (dat->fh, "%9i\r\n", _si); \
307 } \
308 else \
309 fprintf (dat->fh, "%s\r\n", buf); \
310 } \
311 }
312
313 static void
dxf_print_rd(Bit_Chain * dat,BITCODE_RD value,int dxf)314 dxf_print_rd (Bit_Chain *dat, BITCODE_RD value, int dxf)
315 {
316 if (dxf)
317 {
318 char _buf[128];
319 int k;
320 fprintf (dat->fh, "%3i\r\n", dxf);
321 #ifndef DEBUG_CLASSES
322 if (bit_isnan (value))
323 value = 0.0;
324 #endif
325 snprintf (_buf, 127, DXF_FORMAT_FLT, value);
326 k = strlen (_buf);
327 if (strrchr (_buf, '.') && _buf[k - 1] == '0')
328 {
329 for (k--; k > 1 && _buf[k - 1] != '.' && _buf[k] == '0'; k--)
330 _buf[k] = '\0';
331 }
332 // max len 17 resp. 18 with -
333 if (value < 0.0)
334 _buf[DXF_FLT_MAXLEN+1] = '\0';
335 else
336 _buf[DXF_FLT_MAXLEN] = '\0';
337 fprintf (dat->fh, "%s\r\n", _buf);
338 }
339 }
340 #define VALUE_BSd(value, dxf) \
341 if (dxf) \
342 { \
343 GROUP (dxf); \
344 fprintf (dat->fh, "%6i\r\n", value); \
345 }
346 #define VALUE_RD(value, dxf) dxf_print_rd (dat, value, dxf)
347 #define VALUE_B(value, dxf) \
348 if (dxf) \
349 { \
350 GROUP (dxf); \
351 if (value == 0) \
352 fprintf (dat->fh, " 0\r\n"); \
353 else \
354 fprintf (dat->fh, " 1\r\n"); \
355 }
356
357 #define FIELD_HANDLE_NAME(nam, dxf, table) \
358 { \
359 Dwg_Object_Ref *ref = _obj->nam; \
360 Dwg_Object *o = ref ? ref->obj : NULL; \
361 if (o && strEQc (o->dxfname, #table)) \
362 dxf_cvt_tablerecord ( \
363 dat, o, o ? o->tio.object->tio.table->name : (char *)"0", dxf); \
364 else \
365 { \
366 VALUE_TFF ("", dxf) \
367 } \
368 }
369 #define SUB_FIELD_HANDLE_NAME(ob, nam, dxf, table) \
370 { \
371 Dwg_Object_Ref *ref = _obj->ob.nam; \
372 Dwg_Object *o = ref ? ref->obj : NULL; \
373 if (o && strEQc (o->dxfname, #table)) \
374 dxf_cvt_tablerecord ( \
375 dat, o, o ? o->tio.object->tio.table->name : (char *)"0", dxf); \
376 else \
377 { \
378 VALUE_TFF ("", dxf) \
379 } \
380 }
381 #define HEADER_HANDLE_NAME(nam, dxf, table) \
382 HEADER_9 (nam); \
383 FIELD_HANDLE_NAME (nam, dxf, table)
384
385 #define FIELD_DATAHANDLE(nam, code, dxf) \
386 { \
387 Dwg_Object_Ref *ref = _obj->nam; \
388 char s[16]; \
389 HEADER_9 (nam); \
390 VALUE_H (ref ? ref->handleref.value : 0UL, dxf); \
391 }
392
393 #define HEADER_RC(nam, dxf) \
394 HEADER_9 (nam); \
395 FIELDG (nam, RC, dxf)
396 #define HEADER_RC0(nam, dxf) \
397 if (FIELD_VALUE (nam)) \
398 { \
399 HEADER_9 (nam); \
400 FIELDG (nam, RC, dxf); \
401 }
402 #define HEADER_RS(nam, dxf) \
403 { \
404 HEADER_9 (nam); \
405 FIELDG (nam, RS, dxf); \
406 }
407 #define HEADER_RS0(nam, dxf) \
408 if (FIELD_VALUE (nam)) \
409 { \
410 HEADER_9 (nam); \
411 FIELDG (nam, RS, dxf); \
412 }
413 #define HEADER_RD(nam, dxf) \
414 { \
415 HEADER_9 (nam); \
416 FIELD_RD (nam, dxf); \
417 }
418 #define HEADER_RL(nam, dxf) \
419 { \
420 HEADER_9 (nam); \
421 FIELDG (nam, RL, dxf); \
422 }
423 #define HEADER_RLL(nam, dxf) \
424 HEADER_9 (nam); \
425 FIELDG (nam, RLL, dxf)
426 #define HEADER_TV(nam, dxf) \
427 HEADER_9 (nam); \
428 VALUE_TV (_obj->nam, dxf)
429 #define HEADER_TU(nam, dxf) \
430 HEADER_9 (nam); \
431 VALUE_TU (_obj->nam, dxf)
432 #define HEADER_T(nam, dxf) \
433 HEADER_9 (nam); \
434 VALUE_T ((char *)_obj->nam, dxf)
435 #define HEADER_T0(nam, dxf) \
436 if (dxf && !bit_empty_T (dat, _obj->nam)) \
437 { \
438 HEADER_9 (nam); \
439 VALUE_T ((char*)_obj->nam, dxf); \
440 }
441 #define HEADER_B(nam, dxf) \
442 HEADER_9 (nam); \
443 FIELD_B (nam, dxf)
444 #define HEADER_BS(nam, dxf) \
445 HEADER_9 (nam); \
446 FIELDG (nam, BS, dxf)
447 #define HEADER_BSd(nam, dxf) HEADER_BS(nam, dxf)
448 #define HEADER_BD(nam, dxf) \
449 HEADER_9 (nam); \
450 FIELD_BD (nam, dxf)
451 #define HEADER_BL(nam, dxf) \
452 HEADER_9 (nam); \
453 FIELDG (nam, BL, dxf)
454 #define HEADER_BLd(nam, dxf) \
455 HEADER_9 (nam); \
456 FIELDG (nam, BLd, dxf)
457
458 #define VALUE_BB(value, dxf) VALUE (value, RC, dxf)
459 #define VALUE_3B(value, dxf) VALUE (value, RC, dxf)
460 #define VALUE_BS(value, dxf) VALUE (value, RS, dxf)
461 #define VALUE_BL(value, dxf) VALUE (value, BL, dxf)
462 #define VALUE_BLL(value, dxf) VALUE (value, RLL, dxf)
463 #define VALUE_BD(value, dxf) \
464 { \
465 if (dxf >= 50 && dxf < 55) \
466 { \
467 BITCODE_RD _f = rad2deg (value); \
468 VALUE_RD (_f, dxf); \
469 } \
470 else \
471 { \
472 VALUE_RD (value, dxf); \
473 } \
474 }
475 #define VALUE_RC(value, dxf) VALUE (value, RC, dxf)
476 #define VALUE_RS(value, dxf) VALUE (value, RS, dxf)
477 #define VALUE_RL(value, dxf) VALUE (value, RL, dxf)
478 #define VALUE_RLd(value, dxf) VALUE (value, RL, dxf)
479 #define VALUE_RLL(value, dxf) VALUE (value, RLL, dxf)
480 #define VALUE_MC(value, dxf) VALUE (value, MC, dxf)
481 #define VALUE_MS(value, dxf) VALUE (value, MS, dxf)
482 #define VALUE_2RD(pt, dxf) \
483 { \
484 VALUE_RD (pt.x, dxf); \
485 VALUE_RD (pt.y, dxf + 10); \
486 }
487 #define VALUE_3BD(pt, dxf) \
488 { \
489 VALUE_RD (pt.x, dxf); \
490 VALUE_RD (pt.y, dxf + 10); \
491 VALUE_RD (pt.z, dxf + 20); \
492 }
493
494 #define FIELD_RD(nam, dxf) VALUE_RD (_obj->nam, dxf)
495 #define FIELD_B(nam, dxf) VALUE_B (_obj->nam, dxf)
496 #define FIELD_BB(nam, dxf) FIELDG (nam, BB, dxf)
497 #define FIELD_3B(nam, dxf) FIELDG (nam, 3B, dxf)
498 #define FIELD_BS(nam, dxf) FIELDG (nam, BS, dxf)
499 #define FIELD_BSd(nam, dxf) FIELDG (nam, BSd, dxf)
500 #define FIELD_BL(nam, dxf) FIELDG (nam, BL, dxf)
501 #define FIELD_BLL(nam, dxf) FIELDG (nam, BLL, dxf)
502 #define FIELD_BD(nam, dxf) VALUE_BD (_obj->nam, dxf)
503 #define FIELD_RC(nam, dxf) FIELDG (nam, RC, dxf)
504 #define FIELD_RS(nam, dxf) FIELDG (nam, RS, dxf)
505 #define FIELD_RL(nam, dxf) FIELDG (nam, RL, dxf)
506 #define FIELD_RLL(nam, dxf) FIELDG (nam, RLL, dxf)
507 #define FIELD_MC(nam, dxf) FIELDG (nam, MC, dxf)
508 #define FIELD_MS(nam, dxf) FIELDG (nam, MS, dxf)
509 #define FIELD_TF(nam, len, dxf) VALUE_TV (_obj->nam, dxf)
510 #define FIELD_TFF(nam, len, dxf) VALUE_TV (_obj->nam, dxf)
511 #define FIELD_TV(nam, dxf) \
512 if (dxf) \
513 { \
514 VALUE_TV (_obj->nam, dxf); \
515 }
516 #define FIELD_TU(nam, dxf) \
517 if (dxf) \
518 { \
519 VALUE_TU ((BITCODE_TU)_obj->nam, dxf); \
520 }
521 #define FIELD_T(nam, dxf) \
522 { \
523 if (IS_FROM_TU (dat)) \
524 { \
525 FIELD_TU (nam, dxf); \
526 } \
527 else \
528 { \
529 FIELD_TV (nam, dxf); \
530 } \
531 }
532 #define VALUE_T(value, dxf) \
533 { \
534 if (IS_FROM_TU (dat)) \
535 { \
536 VALUE_TU (value, dxf); \
537 } \
538 else \
539 { \
540 VALUE_TV (value, dxf); \
541 } \
542 }
543 #define VALUE_T0(value, dxf) \
544 if (!bit_empty_T (dat, value)) VALUE_T (value,dxf)
545 #define FIELD_BT(nam, dxf) FIELDG (nam, BT, dxf);
546 #define FIELD_4BITS(nam, dxf) FIELDG (nam, 4BITS, dxf)
547 #define FIELD_BE(nam, dxf) \
548 { \
549 if (dxf && !(_obj->nam.x == 0.0 && _obj->nam.y == 0.0 && _obj->nam.z == 1.0)) \
550 FIELD_3RD (nam, dxf) \
551 }
552 // skip if 0
553 #define FIELD_RD0(nam, dxf) FIELD_BD0(nam, dxf)
554 #define FIELD_BD0(nam, dxf) \
555 if (dxf) { \
556 if (_obj->nam != 0.0) \
557 FIELD_BD (nam, dxf) \
558 }
559 // for scale (1.0, 1.0, 1.0) and width_factor
560 #define FIELD_RD1(nam, dxf) FIELD_BD1(nam, dxf)
561 #define FIELD_BD1(nam, dxf) \
562 if (dxf) { \
563 if (_obj->nam != 1.0) \
564 FIELD_BD (nam, dxf) \
565 }
566 #define FIELD_BL0(nam, dxf) \
567 if (dxf) { \
568 if (_obj->nam != 0) \
569 FIELD_BL (nam, dxf) \
570 }
571 #define FIELD_BS0(nam, dxf) \
572 if (dxf) { \
573 if (_obj->nam != 0) \
574 FIELD_BS (nam, dxf) \
575 }
576 #define FIELD_BS1(nam, dxf) \
577 if (dxf) { \
578 if (_obj->nam != 1) \
579 FIELD_BS (nam, dxf) \
580 }
581 #define FIELD_B0(nam, dxf) \
582 if (dxf) { \
583 if (_obj->nam) \
584 FIELD_B (nam, dxf) \
585 }
586 #define FIELD_RC0(nam, dxf) \
587 { \
588 if (_obj->nam != 0) \
589 FIELD_RC (nam, dxf) \
590 }
591 #define FIELD_RS0(nam, dxf) \
592 { \
593 if (_obj->nam != 0) \
594 FIELD_RS (nam, dxf) \
595 }
596 #define FIELD_RL0(nam, dxf) \
597 { \
598 if (_obj->nam != 0) \
599 FIELD_RL (nam, dxf) \
600 }
601 #define FIELD_BT0(nam, dxf) \
602 { \
603 if (_obj->nam != 0) \
604 FIELD_BT (nam, dxf) \
605 }
606 #define FIELD_T0(nam, dxf) \
607 { \
608 if (_obj->nam) \
609 { \
610 if (IS_FROM_TU (dat)) \
611 { \
612 char *u8 = bit_convert_TU ((BITCODE_TU)_obj->nam); \
613 if (u8 && *u8) \
614 { \
615 GROUP (dxf); \
616 fprintf (dat->fh, "%s\r\n", u8); \
617 } \
618 free (u8); \
619 } \
620 else if (*_obj->nam) \
621 { \
622 FIELD_TV (nam, dxf); \
623 } \
624 } \
625 }
626 #define FIELD_TV0(nam, dxf) VALUE_TV0 (_obj->nam, dxf)
627 #define SUB_FIELD_BL0(o, nam, dxf) \
628 { \
629 if (_obj->o.nam != 0) \
630 SUB_FIELD_BL (o, nam, dxf) \
631 }
632
633 #define FIELD_DD(nam, _default, dxf) FIELD_BD (nam, dxf)
634 #define FIELD_2DD(nam, def, dxf) \
635 if (dxf) { \
636 FIELD_DD (nam.x, FIELD_VALUE (def.x), dxf); \
637 FIELD_DD (nam.y, FIELD_VALUE (def.y), dxf + 10); \
638 }
639 #define FIELD_3DD(nam, def, dxf) \
640 if (dxf) { \
641 FIELD_DD (nam.x, FIELD_VALUE (def.x), dxf); \
642 FIELD_DD (nam.y, FIELD_VALUE (def.y), dxf + 10); \
643 FIELD_DD (nam.z, FIELD_VALUE (def.z), dxf + 20); \
644 }
645 #define FIELD_2RD(nam, dxf) \
646 if (dxf) { \
647 FIELD_RD (nam.x, dxf); \
648 FIELD_RD (nam.y, dxf + 10); \
649 }
650 #define FIELD_2RD0(nam, dxf) \
651 if (dxf && _obj->nam.x != 0.0 && _obj->nam.y != 0.0) { \
652 FIELD_RD (nam.x, dxf); \
653 FIELD_RD (nam.y, dxf + 10); \
654 }
655 #define FIELD_2BD(nam, dxf) \
656 if (dxf) { \
657 FIELD_BD (nam.x, dxf); \
658 FIELD_BD (nam.y, dxf + 10); \
659 }
660 #define FIELD_2BD_1(nam, dxf) \
661 if (dxf) { \
662 FIELD_BD (nam.x, dxf); \
663 FIELD_BD (nam.y, dxf + 1); \
664 }
665 #define FIELD_3RD(nam, dxf) \
666 if (dxf) { \
667 FIELD_RD (nam.x, dxf); \
668 FIELD_RD (nam.y, dxf + 10); \
669 FIELD_RD (nam.z, dxf + 20); \
670 }
671 #define FIELD_3BD(nam, dxf) \
672 if (dxf) { \
673 FIELD_BD (nam.x, dxf); \
674 FIELD_BD (nam.y, dxf + 10); \
675 FIELD_BD (nam.z, dxf + 20); \
676 }
677 #define FIELD_3BD_1(nam, dxf) \
678 if (dxf) { \
679 FIELD_BD (nam.x, dxf); \
680 FIELD_BD (nam.y, dxf + 1); \
681 FIELD_BD (nam.z, dxf + 2); \
682 }
683 #define FIELD_3DPOINT(nam, dxf) FIELD_3BD (nam, dxf)
684
685 #define FIELD_CMC(color, dxf) dxf_CMC (dat, (Dwg_Color*)&_obj->color, dxf, 0)
686 #define SUB_FIELD_CMC(o, color, dxf) dxf_CMC (dat, (Dwg_Color*)&_obj->o.color, dxf, 0)
687 #define FIELD_CMC0(color, dxf) dxf_CMC (dat, (Dwg_Color*)&_obj->color, dxf, 1)
688
689 #define HEADER_TIMEBLL(nam, dxf) { \
690 HEADER_9 (nam); \
691 FIELD_TIMEBLL (nam, dxf); \
692 }
693 #define FIELD_TIMEBLL(nam, dxf) \
694 GROUP (dxf); \
695 fprintf (dat->fh, "%.09f\r\n", _obj->nam.value)
696 #define HEADER_CMC(nam, dxf) \
697 HEADER_9 (nam); \
698 VALUE_RS (dwg->header_vars.nam.index, dxf)
699
700 #define POINT_3D(nam, var, c1, c2, c3) \
701 { \
702 VALUE_RD (dwg->var.x, c1); \
703 VALUE_RD (dwg->var.y, c2); \
704 VALUE_RD (dwg->var.z, c3); \
705 }
706 #define POINT_2D(nam, var, c1, c2) \
707 { \
708 VALUE_RD (dwg->var.x, c1); \
709 VALUE_RD (dwg->var.y, c2); \
710 }
711
712 // FIELD_VECTOR_N(nam, type, size):
713 // reads data of the type indicated by 'type' 'size' times and stores
714 // it all in the vector called 'nam'.
715 #define FIELD_VECTOR_N(nam, type, size, dxf) \
716 if (dxf && _obj->nam) \
717 { \
718 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
719 { \
720 VALUE_##type (_obj->nam[vcount], dxf); \
721 } \
722 }
723 #define FIELD_VECTOR_N1(nam, type, size, dxf) \
724 if (dxf && _obj->nam) \
725 { \
726 int _dxf = dxf; \
727 for (vcount = 0; vcount < (BITCODE_BL)size; _dxf++, vcount++) \
728 { \
729 VALUE_##type (_obj->nam[vcount], _dxf); \
730 } \
731 }
732 #define FIELD_VECTOR_T(nam, type, size, dxf) \
733 if (dxf && _obj->nam) \
734 { \
735 if (IS_FROM_TU (dat)) \
736 { \
737 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
738 VALUE_TU (_obj->nam[vcount], dxf); \
739 } \
740 else \
741 { \
742 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
743 VALUE_TV (_obj->nam[vcount], dxf); \
744 } \
745 }
746
747 #define FIELD_VECTOR(nam, type, size, dxf) \
748 FIELD_VECTOR_N (nam, type, _obj->size, dxf)
749
750 #define FIELD_2RD_VECTOR(nam, size, dxf) \
751 if (dxf && _obj->nam) \
752 { \
753 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
754 { \
755 FIELD_2RD (nam[vcount], dxf); \
756 } \
757 }
758
759 #define FIELD_2DD_VECTOR(nam, size, dxf) \
760 FIELD_2RD (nam[0], dxf); \
761 if (dxf && _obj->nam) \
762 { \
763 for (vcount = 1; vcount < (BITCODE_BL)_obj->size; vcount++) \
764 { \
765 FIELD_2DD (nam[vcount], nam[vcount - 1], dxf); \
766 } \
767 }
768
769 #define FIELD_3DPOINT_VECTOR(nam, size, dxf) \
770 if (dxf) \
771 { \
772 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
773 { \
774 FIELD_3DPOINT (nam[vcount], dxf); \
775 } \
776 }
777
778 #define VALUE_HANDLE_N(hdlptr, nam, vcount, handle_code, dxf) \
779 if (dxf && hdlptr && size) \
780 { \
781 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
782 { \
783 VALUE_HANDLE (hdlptr[vcount], nam, handle_code, dxf); \
784 } \
785 }
786 #define FIELD_HANDLE_N(nam, size, handle_code, dxf) \
787 VALUE_HANDLE (_obj->nam, nam, handle_code, dxf)
788 #define HANDLE_VECTOR_N(nam, size, code, dxf) \
789 if (dxf && _obj->nam && size) \
790 { \
791 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
792 { \
793 FIELD_HANDLE (nam[vcount], code, dxf); \
794 } \
795 }
796
797 #define HANDLE_VECTOR(nam, sizefield, code, dxf) \
798 HANDLE_VECTOR_N (nam, FIELD_VALUE (sizefield), code, dxf)
799
800 #define FIELD_NUM_INSERTS(num_inserts, type, dxf) \
801 FIELDG (num_inserts, type, dxf)
802
803 #define FIELD_XDATA(nam, size) \
804 dxf_write_xdata (dat, obj, _obj->nam, _obj->size)
805
806 #define _XDICOBJHANDLE(code) \
807 if (dat->version >= R_13 && obj->tio.object->xdicobjhandle \
808 && obj->tio.object->xdicobjhandle->absolute_ref) \
809 { \
810 fprintf (dat->fh, "102\r\n{ACAD_XDICTIONARY\r\n"); \
811 VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, \
812 360); \
813 fprintf (dat->fh, "102\r\n}\r\n"); \
814 }
815 #define _REACTORS(code) \
816 if (dat->version >= R_13 && obj->tio.object->num_reactors \
817 && obj->tio.object->reactors) \
818 { \
819 fprintf (dat->fh, "102\r\n{ACAD_REACTORS\r\n"); \
820 for (vcount = 0; vcount < obj->tio.object->num_reactors; vcount++) \
821 { /* soft ptr */ \
822 VALUE_HANDLE (obj->tio.object->reactors[vcount], reactors, code, \
823 330); \
824 } \
825 fprintf (dat->fh, "102\r\n}\r\n"); \
826 }
827 #define ENT_REACTORS(code) \
828 if (dat->version >= R_13 && _obj->num_reactors && _obj->reactors) \
829 { \
830 fprintf (dat->fh, "102\r\n{ACAD_REACTORS\r\n"); \
831 for (vcount = 0; vcount < _obj->num_reactors; vcount++) \
832 { \
833 VALUE_HANDLE (_obj->reactors[vcount], reactors, code, 330); \
834 } \
835 fprintf (dat->fh, "102\r\n}\r\n"); \
836 }
837 #define REACTORS(code)
838 #define XDICOBJHANDLE(code)
839 #define ENT_XDICOBJHANDLE(code) \
840 if (dat->version >= R_13 && obj->tio.entity->xdicobjhandle \
841 && obj->tio.entity->xdicobjhandle->absolute_ref) \
842 { \
843 fprintf (dat->fh, "102\r\n{ACAD_XDICTIONARY\r\n"); \
844 VALUE_HANDLE (obj->tio.entity->xdicobjhandle, xdicobjhandle, code, \
845 360); \
846 fprintf (dat->fh, "102\r\n}\r\n"); \
847 }
848 #define BLOCK_NAME(nam, dxf) dxf_cvt_blockname (dat, _obj->nam, dxf)
849
850 #define COMMON_ENTITY_HANDLE_DATA
851 #define SECTION_STRING_STREAM
852 #define START_STRING_STREAM
853 #define END_STRING_STREAM
854 #define START_HANDLE_STREAM
855
856 #ifndef DEBUG_CLASSES
857 static int
dwg_dxf_TABLECONTENT(Bit_Chain * restrict dat,const Dwg_Object * restrict obj)858 dwg_dxf_TABLECONTENT (Bit_Chain *restrict dat, const Dwg_Object *restrict obj)
859 {
860 (void)dat;
861 (void)obj;
862 return 0;
863 }
864 #else
865 static int dwg_dxf_TABLECONTENT (Bit_Chain *restrict dat,
866 const Dwg_Object *restrict obj);
867 #endif
868
869 // The strcmp is being optimized away at compile-time!
870 // https://godbolt.org/g/AqkhwL
871 #define DWG_ENTITY(token) \
872 static int dwg_dxf_##token##_private ( \
873 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
874 const Dwg_Object *restrict obj); \
875 static int dwg_dxf_##token (Bit_Chain *restrict dat, \
876 const Dwg_Object *restrict obj) \
877 { \
878 int error = 0; \
879 Bit_Chain *hdl_dat = dat; \
880 Bit_Chain *str_dat = dat; \
881 if (obj->fixedtype != DWG_TYPE_##token) \
882 { \
883 LOG_ERROR ("Invalid type 0x%x, expected 0x%x %s", obj->fixedtype, \
884 DWG_TYPE_##token, #token); \
885 return DWG_ERR_INVALIDTYPE; \
886 } \
887 if (strEQc (#token, "GEOPOSITIONMARKER")) \
888 RECORD (POSITIONMARKER); \
889 else if (dat->version < R_13 && strlen (#token) == 10 \
890 && strEQc (#token, "LWPOLYLINE")) \
891 RECORD (POLYLINE); \
892 else if (strlen (#token) > 10 && !memcmp (#token, "DIMENSION_", 10)) \
893 RECORD (DIMENSION); \
894 else if (strlen (#token) > 9 && !memcmp (#token, "POLYLINE_", 9)) \
895 RECORD (POLYLINE); \
896 else if (strlen (#token) > 7 && !memcmp (#token, "VERTEX_", 7)) \
897 RECORD (VERTEX); \
898 else if (strEQc (#token, "MINSERT")) \
899 RECORD (INSERT); \
900 else if (dat->version >= R_2010 && strEQc (#token, "TABLE")) \
901 { \
902 RECORD (ACAD_TABLE); \
903 return dwg_dxf_TABLECONTENT (dat, obj); \
904 } \
905 else if (strlen (#token) > 3 && !memcmp (#token, "_3D", 3)) \
906 record (obj->dxfname); \
907 else if (obj->type >= 498 && obj->dxfname) \
908 record (obj->dxfname); \
909 else \
910 RECORD (token); \
911 LOG_INFO ("Entity " #token ":\n") \
912 SINCE (R_11) \
913 { \
914 LOG_TRACE ("Entity handle: " FORMAT_H "\n", ARGS_H (obj->handle)); \
915 fprintf (dat->fh, "%3i\r\n%lX\r\n", 5, obj->handle.value); \
916 } \
917 SINCE (R_13) { error |= dxf_common_entity_handle_data (dat, obj); } \
918 error |= dwg_dxf_##token##_private (dat, hdl_dat, str_dat, obj); \
919 error |= dxf_write_eed (dat, obj->tio.object); \
920 return error; \
921 } \
922 static int dwg_dxf_##token##_private ( \
923 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
924 const Dwg_Object *restrict obj) { \
925 int error = 0; \
926 BITCODE_BL vcount, rcount3, rcount4; \
927 Dwg_Data *dwg = obj->parent; \
928 Dwg_Entity_##token *_obj = obj->tio.entity->tio.token; \
929 Dwg_Object_Entity *_ent = obj->tio.entity;
930
931 #define DWG_ENTITY_END \
932 return error; \
933 }
934
935 #define DWG_OBJECT(token) \
936 static int dwg_dxf_##token##_private ( \
937 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
938 const Dwg_Object *restrict obj); \
939 static int dwg_dxf_##token (Bit_Chain *restrict dat, \
940 const Dwg_Object *restrict obj) \
941 { \
942 int error = 0; \
943 Bit_Chain *hdl_dat = dat, *str_dat = dat; \
944 LOG_INFO ("Object " #token ":\n") \
945 if (obj->fixedtype != DWG_TYPE_##token) \
946 { \
947 LOG_ERROR ("Invalid type 0x%x, expected 0x%x %s", obj->fixedtype, \
948 DWG_TYPE_##token, #token); \
949 return DWG_ERR_INVALIDTYPE; \
950 } \
951 PRE (R_14) { \
952 if (obj->fixedtype == DWG_TYPE_PLACEHOLDER) \
953 return 0; \
954 } \
955 if (!dwg_obj_is_control (obj)) \
956 { \
957 if (obj->fixedtype == DWG_TYPE_TABLE) \
958 ; \
959 else if (obj->type >= 500 && obj->dxfname) \
960 fprintf (dat->fh, " 0\r\n%s\r\n", obj->dxfname); \
961 else if (obj->type == DWG_TYPE_PLACEHOLDER) \
962 RECORD (ACDBPLACEHOLDER); \
963 else if (obj->fixedtype == DWG_TYPE_PROXY_OBJECT) \
964 RECORD (ACAD_PROXY_OBJECT); \
965 else if (obj->type != DWG_TYPE_BLOCK_HEADER) \
966 RECORD (token); \
967 \
968 SINCE (R_13) \
969 { \
970 BITCODE_BL vcount; \
971 const int dxf = obj->type == DWG_TYPE_DIMSTYLE ? 105 : 5; \
972 VALUE_H (obj->handle.value, dxf); \
973 _XDICOBJHANDLE (3); \
974 _REACTORS (4); \
975 } \
976 SINCE (R_14) \
977 { \
978 VALUE_HANDLE (obj->tio.object->ownerhandle, ownerhandle, 3, 330); \
979 } \
980 } \
981 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE) \
982 { \
983 if (dwg_obj_is_table (obj)) \
984 { \
985 char *_name = dwg_obj_table_get_name (obj, &error); \
986 LOG_TRACE ("Object handle: " FORMAT_H ", name: %s\n", \
987 ARGS_H (obj->handle), _name); \
988 if (IS_FROM_TU (dat)) \
989 free (_name); \
990 } \
991 else \
992 LOG_TRACE ("Object handle: " FORMAT_H "\n", ARGS_H (obj->handle)) \
993 } \
994 error |= dwg_dxf_##token##_private (dat, hdl_dat, str_dat, obj); \
995 error |= dxf_write_eed (dat, obj->tio.object); \
996 return error; \
997 } \
998 static int dwg_dxf_##token##_private ( \
999 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
1000 const Dwg_Object *restrict obj) { \
1001 int error = 0; \
1002 BITCODE_BL vcount, rcount3, rcount4; \
1003 Dwg_Data *dwg = obj->parent; \
1004 Dwg_Object_##token *_obj = obj->tio.object->tio.token;
1005
1006 // then 330, SUBCLASS
1007
1008 #define DWG_OBJECT_END \
1009 return error; \
1010 }
1011
1012 #undef DXF_3DSOLID
1013 #define DXF_3DSOLID dxf_3dsolid (dat, obj, (Dwg_Entity_3DSOLID *)_obj);
1014
1015 // Skip index 256 bylayer
1016 // 257 is for method c8 NONE. Which index is for ByBlock?
1017 // If the dxf code is 90-99 rather emit the rgb only
dxf_CMC(Bit_Chain * restrict dat,Dwg_Color * restrict color,const int dxf,const int opt)1018 static void dxf_CMC (Bit_Chain *restrict dat, Dwg_Color *restrict color,
1019 const int dxf, const int opt)
1020 {
1021 if (dat->version >= R_2004)
1022 {
1023 if (dat->from_version < R_2004)
1024 bit_upconvert_CMC (dat, color);
1025 if (dxf >= 90)
1026 {
1027 VALUE_RLd (color->rgb, dxf);
1028 return;
1029 }
1030 else if (color->method == 0xc3)
1031 {
1032 VALUE_RS (color->rgb & 0x00ffffff, dxf);
1033 return;
1034 }
1035 else if (color->method == 0xc8)
1036 {
1037 VALUE_RS (257, dxf);
1038 return;
1039 }
1040 if (!opt || color->index)
1041 {
1042 VALUE_RS (color->index, dxf);
1043 }
1044 if (color->method != 0xc2)
1045 return;
1046 VALUE_RL (color->rgb, dxf + 420 - 62);
1047 if (color->flag & 2 && color->book_name)
1048 {
1049 char name[256];
1050 if (IS_FROM_TU (dat))
1051 {
1052 char *u8 = bit_convert_TU ((BITCODE_TU)color->book_name);
1053 if (u8)
1054 strncpy (name, u8, 127);
1055 else
1056 name[0] = '\0';
1057 free (u8);
1058 u8 = bit_convert_TU ((BITCODE_TU)color->name);
1059 if (u8)
1060 {
1061 if (*name)
1062 strcat (name, "$");
1063 strncat (name, u8, 127);
1064 free (u8);
1065 }
1066 }
1067 else
1068 {
1069 strncpy (name, color->book_name, 127);
1070 if (color->name)
1071 {
1072 strcat (name, "$");
1073 strncat (name, color->name, 127);
1074 }
1075 }
1076 VALUE_TV (name, dxf + 430 - 62);
1077 }
1078 else if (color->flag & 1 && color->name)
1079 {
1080 VALUE_T (color->name, dxf + 430 - 62);
1081 }
1082 else if (color->flag)
1083 {
1084 VALUE_TFF ("UNNAMED", dxf + 430 - 62);
1085 }
1086 }
1087 else
1088 {
1089 bit_downconvert_CMC (dat, color);
1090 VALUE_RS (color->index, dxf);
1091 }
1092 }
1093
1094 /* fixme: shift-jis decoding
1095 "\M+182B1\M+182CC\M+1907D\M+19867\M+182CD\M+18354\M+18393\M+18376\M+1838B\M+182C5\M+182B7\M+18142\M+18ED0\M+193E0\M+182CC\M+18B4B\M+18A69\M+182E2\M+18376\M+1838D\M+18362\M+1835E\M+182CC\M+18F6F\M+197CD\M+194CD\M+188CD\M+182C9\M+18D87\M+182ED\M+182B9\M+182C4\M+1934B\M+19396\M+182C9\M+195CF\M+18D58\M+182B5\M+182C4\M+182B2\M+19798\M+19770\M+182AD\M+182BE\M+182B3\M+182A2\M+18142"
1096 =>
1097 "\U+3053\U+306E\U+56F3\U+67A0\U+306F\U+30B5\U+30F3\U+30D7\U+30EB\U+3067\U+3059\U+3002\U+793E\U+5185\U+306E\U+898F\U+683C\U+3084\U+30D7\U+30ED\U+30C3\U+30BF\U+306E\U+51FA\U+529B\U+7BC4\U+56F2\U+306B\U+5408\U+308F\U+305B\U+3066\U+9069\U+5F53\U+306B\U+5909\U+66F4\U+3057\U+3066\U+3054\U+5229\U+7528\U+304F\U+3060\U+3055\U+3044\U+3002"
1098 */
1099 static char *
cquote(char * restrict dest,const int len,const char * restrict src)1100 cquote (char *restrict dest, const int len, const char *restrict src)
1101 {
1102 char c;
1103 char *d = dest;
1104 const char* dend = dest + len;
1105 const char* send = src + strlen(src);
1106 char *s = (char *)src;
1107 while ((s < send) && (c = *s++) && dest < dend)
1108 {
1109 if (c == '\n' && dest+1 < dend)
1110 {
1111 *dest++ = '^';
1112 *dest++ = 'J';
1113 }
1114 else if (c == '\r' && dest+1 < dend)
1115 {
1116 *dest++ = '^';
1117 *dest++ = 'M';
1118 }
1119 // convert shiftjis \M+1xxxx to \U+xxxx
1120 else if (c == '\\' && dest+7 < dend && memBEGINc (s, "M+1"))
1121 { // e.g. \M+1(8140) => \U+3000, 82a0 => 3042
1122 uint32_t x;
1123 sscanf (&s[3], "%4X", &x);
1124 // just convert a small subset, Hiragana + Katakana letters
1125 // see https://www.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/SHIFTJIS.TXT
1126 if (x < 0x829f) // < Hiragana: 8140 -> 3000: FULLWIDTH LATIN LETTER
1127 x -= 0x5140;
1128 else if (x >= 0x889f) { // CJK
1129 LOG_WARN ("Unsupported \\M+1%04X shift-jis character", x);
1130 x -= (0x889f - 0x404c); // not really
1131 }
1132 else if (x >= 0x839f) // > Katakana: Greek
1133 x -= (0x839f - 0x391);
1134 else
1135 x -= 0x525e; // our safe range of Hiragana + Katakana letters
1136 if (x < 0x10100)
1137 {
1138 snprintf (dest, dend - dest, "\\U+%04X", x);
1139 dest += 7;
1140 s += 7;
1141 }
1142 else
1143 {
1144 LOG_ERROR ("Invalid shift-jis sequence %s", s-1);
1145 s += 3;
1146 }
1147 }
1148 else
1149 *dest++ = c;
1150 }
1151 d[len - 1] = '\0'; // add final delim, skipped above
1152 return d;
1153 }
1154
1155 /* If opts 1:
1156 quote \n => ^J
1157 \M+xxxxx => \U+XXXX (shift-jis)
1158 Splits overlong (len>255) lines into dxf 3 chunks with group 1
1159 */
1160 static void
dxf_fixup_string(Bit_Chain * restrict dat,char * restrict str,const int opts,const int dxf,const int dxfcont)1161 dxf_fixup_string (Bit_Chain *restrict dat, char *restrict str,
1162 const int opts, const int dxf, const int dxfcont)
1163 {
1164 if (str && *str)
1165 {
1166 if (opts && (strchr (str, '\n') || strchr (str, '\r') || strstr (str, "\\M+1")))
1167 {
1168 const int origlen = strlen (str);
1169 int len = (2 * origlen) + 1;
1170 char *_buf;
1171 if (len > 1024)
1172 {
1173 fprintf (dat->fh, "\r\n");
1174 LOG_ERROR ("Overlarge DXF string, len=%d", origlen);
1175 return;
1176 }
1177 _buf = (char *)alloca (len);
1178 if (!_buf)
1179 {
1180 fprintf (dat->fh, "\r\n");
1181 LOG_ERROR ("Out of stack memory");
1182 return;
1183 }
1184 _buf[len - 1] = '\0';
1185 _buf = cquote (_buf, len, str);
1186 if (!_buf)
1187 {
1188 fprintf (dat->fh, "\r\n");
1189 LOG_ERROR ("Out of stack");
1190 return;
1191 }
1192 len = strlen (_buf);
1193 if (len > 255 && dxf == 1)
1194 {
1195 // GROUP 1 already printed
1196 while (len > 0)
1197 {
1198 fprintf (dat->fh, "%.*s\r\n", len > 255 ? 255 : len, _buf);
1199 len -= 255;
1200 _buf += 255;
1201 if (len > 0)
1202 fprintf (dat->fh, "%3d\r\n", dxfcont);
1203 }
1204 }
1205 else
1206 fprintf (dat->fh, "%s\r\n", _buf);
1207 freea (_buf);
1208 }
1209 else
1210 {
1211 int len = strlen (str);
1212 if (len > 255 && dxf == 1)
1213 {
1214 // GROUP 1 already printed
1215 while (len > 0)
1216 {
1217 fprintf (dat->fh, "%.*s\r\n", len > 255 ? 255 : len, str);
1218 len -= 255;
1219 str += 255;
1220 if (len > 0)
1221 fprintf (dat->fh, " 3\r\n");
1222 }
1223 }
1224 else
1225 fprintf (dat->fh, "%s\r\n", str);
1226 }
1227 }
1228 else
1229 fprintf (dat->fh, "\r\n");
1230 }
1231
1232 static int
dxf_write_eed(Bit_Chain * restrict dat,const Dwg_Object_Object * restrict obj)1233 dxf_write_eed (Bit_Chain *restrict dat, const Dwg_Object_Object *restrict obj)
1234 {
1235 int error = 0;
1236 Dwg_Data *dwg = obj->dwg;
1237 for (BITCODE_BL i = 0; i < obj->num_eed; i++)
1238 {
1239 const Dwg_Eed* _obj = &obj->eed[i];
1240 if (_obj->size)
1241 {
1242 // name of APPID
1243 Dwg_Object *appid = dwg_resolve_handle (dwg, _obj->handle.value);
1244 if (appid && appid->fixedtype == DWG_TYPE_APPID)
1245 VALUE_T (appid->tio.object->tio.APPID->name, 1001)
1246 else
1247 VALUE_TFF ("ACAD", 1001);
1248 }
1249 if (_obj->data)
1250 {
1251 const Dwg_Eed_Data *data = _obj->data;
1252 const int dxf = data->code + 1000;
1253 switch (data->code)
1254 {
1255 case 0:
1256 if (!data->u.eed_0.length)
1257 fprintf (dat->fh, "1000\r\n\r\n");
1258 else if (data->u.eed_0.is_tu)
1259 VALUE_TU (data->u.eed_0_r2007.string, 1000)
1260 else
1261 VALUE_TV (data->u.eed_0.string, 1000)
1262 break;
1263 case 2:
1264 if (data->u.eed_2.close)
1265 VALUE_TFF ("}", 1002)
1266 else
1267 VALUE_TFF ("{", 1002)
1268 break;
1269 case 3:
1270 GROUP (dxf);
1271 fprintf (dat->fh, "%9lu\r\n", (unsigned long)data->u.eed_3.layer);
1272 //VALUE_RLL (data->u.eed_3.layer, dxf);
1273 break;
1274 case 4: VALUE_BINARY (data->u.eed_4.data, data->u.eed_4.length, dxf); break;
1275 case 5: VALUE_H (data->u.eed_5.entity, dxf); break; // not in DXF
1276 case 10:
1277 case 11:
1278 case 12:
1279 case 13:
1280 case 14:
1281 case 15: VALUE_3BD (data->u.eed_10.point, dxf); break;
1282 case 40:
1283 case 41:
1284 case 42: VALUE_RD (data->u.eed_40.real, dxf); break;
1285 case 70: VALUE_RS (data->u.eed_70.rs, dxf); break;
1286 case 71: VALUE_RL (data->u.eed_71.rl, dxf); break;
1287 default: VALUE_RC (0, dxf);
1288 }
1289 }
1290 }
1291 return error;
1292 }
1293
1294 /* If the name contains "$0$"
1295 */
1296 bool
dxf_is_xrefdep_name(Bit_Chain * restrict dat,const char * name)1297 dxf_is_xrefdep_name (Bit_Chain *restrict dat,
1298 const char *name)
1299 {
1300 if (IS_FROM_TU (dat))
1301 {
1302 BITCODE_TU wstr = (BITCODE_TU)name;
1303 #if defined (HAVE_NATIVE_WCHAR2) && defined (HAVE_WCSSTR)
1304 if (wstr && *wstr && wcsstr (&wstr[1], L"$0$"))
1305 return true;
1306 else
1307 return false;
1308 #else
1309 bool result;
1310 char* u8 = bit_convert_TU (wstr);
1311 if (u8 && *u8 && strstr (&u8[1], "$0$"))
1312 result = true;
1313 else
1314 result = false;
1315 if (u8)
1316 free (u8);
1317 return result;
1318 #endif
1319 }
1320 else
1321 {
1322 if (name && *name && strstr (&name[1], "$0$"))
1323 return true;
1324 else
1325 return false;
1326 }
1327 }
1328
1329 /* Layer names with active dependent xref have a name like "REF|name",
1330 or "REF|REFNAME$0$name" name.
1331 Otherwise we get Layer name with vertical bar is not marked dependent
1332 (gh44-error_2013)
1333 */
1334 bool
dxf_has_xrefdep_vertbar(Bit_Chain * restrict dat,const char * name)1335 dxf_has_xrefdep_vertbar (Bit_Chain *restrict dat,
1336 const char *name)
1337 {
1338 if (IS_FROM_TU (dat))
1339 {
1340 BITCODE_TU wstr = (BITCODE_TU)name;
1341 #if defined (HAVE_NATIVE_WCHAR2) && defined (HAVE_WCSCHR)
1342 if (wstr && *wstr && wcschr (&wstr[1], L'|'))
1343 return true;
1344 else
1345 return false;
1346 #else
1347 bool result;
1348 char* u8 = bit_convert_TU (wstr);
1349 if (u8 && *u8 && strchr (&u8[1], '|'))
1350 result = true;
1351 else
1352 result = false;
1353 if (u8)
1354 free (u8);
1355 return result;
1356 #endif
1357 }
1358 else
1359 {
1360 if (name && *name && strchr (&name[1], '|'))
1361 return true;
1362 else
1363 return false;
1364 }
1365 }
1366
1367 bool
dxf_has_STYLE_eed(Bit_Chain * restrict dat,const Dwg_Object_Object * restrict obj)1368 dxf_has_STYLE_eed (Bit_Chain *restrict dat,
1369 const Dwg_Object_Object *restrict obj)
1370 {
1371 bool result = false;
1372 bool has_acadappid = false;
1373 Dwg_Data *dwg = obj->dwg;
1374 for (BITCODE_BL i = 0; i < obj->num_eed; i++)
1375 {
1376 const Dwg_Eed* _obj = &obj->eed[i];
1377 if (_obj->size)
1378 {
1379 // check for APPID ACAD and first data to be a string 0. TODO 2nd to be 71
1380 Dwg_Object *appid = dwg_resolve_handle (dwg, _obj->handle.value);
1381 if (appid && appid->fixedtype == DWG_TYPE_APPID &&
1382 bit_eq_T (dat, appid->tio.object->tio.APPID->name, "ACAD"))
1383 {
1384 has_acadappid = true;
1385 if (_obj->data && _obj->data->code == 0)
1386 return true;
1387 }
1388 }
1389 }
1390 return result;
1391 }
1392
1393 GCC30_DIAG_IGNORE (-Wformat-nonliteral)
1394 static int
dxf_write_xdata(Bit_Chain * restrict dat,const Dwg_Object * restrict obj,Dwg_Resbuf * restrict rbuf,BITCODE_BL size)1395 dxf_write_xdata (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
1396 Dwg_Resbuf *restrict rbuf, BITCODE_BL size)
1397 {
1398 Dwg_Resbuf *tmp;
1399 int i;
1400
1401 while (rbuf)
1402 {
1403 const char *fmt;
1404 short type;
1405 int dxftype = rbuf->type;
1406
1407 fmt = dxf_format (rbuf->type);
1408 type = dwg_resbuf_value_type (rbuf->type);
1409 dxftype = (rbuf->type > 1000 || obj->fixedtype == DWG_TYPE_XRECORD)
1410 ? rbuf->type
1411 : rbuf->type + 1000;
1412 if (obj->fixedtype == DWG_TYPE_XRECORD && dxftype >= 80 && dxftype < 90)
1413 {
1414 fmt = "(unknown code)";
1415 type = DWG_VT_INVALID;
1416 }
1417
1418 if (strEQc (fmt, "(unknown code)"))
1419 {
1420 if (type == DWG_VT_INVALID)
1421 {
1422 LOG_WARN ("Invalid xdata code %d", dxftype);
1423 }
1424 else
1425 {
1426 LOG_WARN ("Unknown xdata code %d => %d", dxftype,
1427 (BITCODE_BL)type);
1428 }
1429 }
1430
1431 tmp = rbuf->nextrb;
1432 switch (type)
1433 {
1434 case DWG_VT_STRING:
1435 if (IS_FROM_TU (dat)) { VALUE_TU (rbuf->value.str.u.wdata, dxftype); }
1436 else { VALUE_TV (rbuf->value.str.u.data, dxftype); }
1437 break;
1438 case DWG_VT_REAL:
1439 VALUE_RD (rbuf->value.dbl, dxftype);
1440 break;
1441 case DWG_VT_BOOL:
1442 case DWG_VT_INT8:
1443 VALUE_RC (rbuf->value.i8, dxftype);
1444 break;
1445 case DWG_VT_INT16:
1446 VALUE_RS (rbuf->value.i16, dxftype);
1447 break;
1448 case DWG_VT_INT32:
1449 VALUE_RL (rbuf->value.i32, dxftype);
1450 break;
1451 case DWG_VT_INT64:
1452 VALUE_RLL (rbuf->value.i64, dxftype);
1453 break;
1454 case DWG_VT_POINT3D:
1455 VALUE_RD (rbuf->value.pt[0], dxftype);
1456 VALUE_RD (rbuf->value.pt[1], dxftype + 10);
1457 VALUE_RD (rbuf->value.pt[2], dxftype + 20);
1458 break;
1459 case DWG_VT_BINARY:
1460 VALUE_BINARY (rbuf->value.str.u.data, rbuf->value.str.size, dxftype);
1461 break;
1462 case DWG_VT_HANDLE:
1463 case DWG_VT_OBJECTID:
1464 fprintf (dat->fh, "%3i\r\n%lX\r\n", dxftype,
1465 (unsigned long)*(uint64_t *)rbuf->value.hdl);
1466 break;
1467 case DWG_VT_INVALID:
1468 break; // skip
1469 default:
1470 fprintf (dat->fh, "%3i\r\n\r\n", dxftype);
1471 break;
1472 }
1473 rbuf = tmp;
1474 }
1475 return 0;
1476 }
1477
1478 // r13+ converts STANDARD to Standard, BYLAYER to ByLayer, BYBLOCK to ByBlock
1479 static void
dxf_cvt_tablerecord(Bit_Chain * restrict dat,const Dwg_Object * restrict obj,char * restrict name,const int dxf)1480 dxf_cvt_tablerecord (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
1481 char *restrict name, const int dxf)
1482 {
1483 if (obj && obj->supertype == DWG_SUPERTYPE_OBJECT && name != NULL)
1484 {
1485 if (IS_FROM_TU (dat))
1486 {
1487 name = bit_convert_TU ((BITCODE_TU)name);
1488 }
1489 if (dat->from_version >= R_13 && dat->version < R_13)
1490 { // convert the other way round, from newer to older
1491 if (strEQc (name, "Standard"))
1492 fprintf (dat->fh, "%3i\r\nSTANDARD\r\n", dxf);
1493 else if (strEQc (name, "ByLayer"))
1494 fprintf (dat->fh, "%3i\r\nBYLAYER\r\n", dxf);
1495 else if (strEQc (name, "ByBlock"))
1496 fprintf (dat->fh, "%3i\r\nBYBLOCK\r\n", dxf);
1497 else if (strEQc (name, "*Active"))
1498 fprintf (dat->fh, "%3i\r\n*ACTIVE\r\n", dxf);
1499 else
1500 fprintf (dat->fh, "%3i\r\n%s\r\n", dxf, name);
1501 }
1502 else
1503 { // convert some standard names
1504 if (dat->version >= R_13 && strEQc (name, "STANDARD"))
1505 fprintf (dat->fh, "%3i\r\nStandard\r\n", dxf);
1506 else if (dat->version >= R_13 && strEQc (name, "BYLAYER"))
1507 fprintf (dat->fh, "%3i\r\nByLayer\r\n", dxf);
1508 else if (dat->version >= R_13 && strEQc (name, "BYBLOCK"))
1509 fprintf (dat->fh, "%3i\r\nByBlock\r\n", dxf);
1510 else if (dat->version >= R_13 && strEQc (name, "*ACTIVE"))
1511 fprintf (dat->fh, "%3i\r\n*Active\r\n", dxf);
1512 else
1513 fprintf (dat->fh, "%3i\r\n%s\r\n", dxf, name);
1514 }
1515 if (IS_FROM_TU (dat))
1516 free (name);
1517 }
1518 else
1519 {
1520 fprintf (dat->fh, "%3i\r\n\r\n", dxf);
1521 }
1522 }
1523
1524 /* pre-r13 mspace and pspace blocks have different names:
1525 *Model_Space => $MODEL_SPACE
1526 *Paper_Space => $PAPER_SPACE
1527 TODO: Better use proper EXTNAMES
1528 */
1529 static void
dxf_cvt_blockname(Bit_Chain * restrict dat,char * restrict name,const int dxf)1530 dxf_cvt_blockname (Bit_Chain *restrict dat, char *restrict name, const int dxf)
1531 {
1532 if (!name)
1533 {
1534 fprintf (dat->fh, "%3i\r\n\r\n", dxf);
1535 return;
1536 }
1537 if (IS_FROM_TU (dat)) // r2007+ unicode names
1538 {
1539 name = bit_convert_TU ((BITCODE_TU)name);
1540 }
1541 if (dat->version == dat->from_version) // no conversion
1542 {
1543 fprintf (dat->fh, "%3i\r\n%s\r\n", dxf, name);
1544 }
1545 else if (dat->version < R_13 && dat->from_version >= R_13) // to older
1546 {
1547 if (strlen (name) < 10)
1548 fprintf (dat->fh, "%3i\r\n%s\r\n", dxf, name);
1549 else if (strEQc (name, "*Model_Space"))
1550 fprintf (dat->fh, "%3i\r\n$MODEL_SPACE\r\n", dxf);
1551 else if (strEQc (name, "*Paper_Space"))
1552 fprintf (dat->fh, "%3i\r\n$PAPER_SPACE\r\n", dxf);
1553 else if (!memcmp (name, "*Paper_Space", sizeof ("*Paper_Space") - 1))
1554 fprintf (dat->fh, "%3i\r\n$PAPER_SPACE%s\r\n", dxf, &name[12]);
1555 else
1556 fprintf (dat->fh, "%3i\r\n%s\r\n", dxf, name);
1557 }
1558 else if (dat->version >= R_13 && dat->from_version < R_13) // to newer
1559 {
1560 if (strlen (name) < 10)
1561 fprintf (dat->fh, "%3i\r\n%s\r\n", dxf, name);
1562 else if (strEQc (name, "$MODEL_SPACE"))
1563 fprintf (dat->fh, "%3i\r\n*Model_Space\r\n", dxf);
1564 else if (strEQc (name, "$PAPER_SPACE"))
1565 fprintf (dat->fh, "%3i\r\n*Paper_Space\r\n", dxf);
1566 else if (!memcmp (name, "$PAPER_SPACE", sizeof ("$PAPER_SPACE") - 1))
1567 fprintf (dat->fh, "%3i\r\n*Paper_Space%s\r\n", dxf, &name[12]);
1568 else
1569 fprintf (dat->fh, "%3i\r\n%s\r\n", dxf, name);
1570 }
1571 if (IS_FROM_TU (dat))
1572 {
1573 free (name);
1574 name = NULL;
1575 }
1576 }
1577
1578 #define START_OBJECT_HANDLE_STREAM
1579
1580 // Handle 5 written here first
1581 #define COMMON_TABLE_CONTROL_FLAGS \
1582 if (ctrl) \
1583 { \
1584 SINCE (R_13) \
1585 { \
1586 VALUE_H (ctrl->handle.value, 5); \
1587 _XDICOBJHANDLE (3); \
1588 _REACTORS (4); \
1589 } \
1590 SINCE (R_14) \
1591 { \
1592 VALUE_HANDLE (ctrl->tio.object->ownerhandle, ownerhandle, 3, 330); \
1593 } \
1594 } \
1595 SINCE (R_13) { VALUE_TV ("AcDbSymbolTable", 100); }
1596
1597 #define COMMON_TABLE_FLAGS(acdbname) \
1598 SINCE (R_13) \
1599 { \
1600 VALUE_TV ("AcDbSymbolTableRecord", 100); \
1601 VALUE_TV ("AcDb" #acdbname "TableRecord", 100); \
1602 } \
1603 if (strEQc (#acdbname, "Block") && dat->version >= R_13) \
1604 { \
1605 Dwg_Object *blk = dwg_ref_object ( \
1606 dwg, ((Dwg_Object_BLOCK_HEADER *)_obj)->block_entity); \
1607 if (blk && blk->type == DWG_TYPE_BLOCK) \
1608 { \
1609 Dwg_Entity_BLOCK *_blk = blk->tio.entity->tio.BLOCK; \
1610 VALUE_T (_blk->name, 2) \
1611 } \
1612 else if (_obj->name) \
1613 { \
1614 VALUE_T (_obj->name, 2) \
1615 } \
1616 else \
1617 VALUE_TV ("*", 2) \
1618 } \
1619 /* Empty name with xref shape names */ \
1620 else if (strEQc (#acdbname, "TextStyle") && \
1621 _obj->flag & 1 && \
1622 dxf_is_xrefdep_name (dat, _obj->name)) \
1623 VALUE_TV ("", 2) \
1624 else if (_obj->name) \
1625 dxf_cvt_tablerecord (dat, obj, _obj->name, 2); \
1626 else \
1627 VALUE_TV ("*", 2) \
1628 if (strEQc (#acdbname, "Layer") && dat->version >= R_2000) \
1629 { \
1630 /* Mask off plotflag and linewt. */ \
1631 BITCODE_RC _flag = _obj->flag & ~0x3e0; \
1632 /* Don't keep bit 16 when not xrefdep like "XREF|name" */ \
1633 if (_flag & 0x10 && !dxf_has_xrefdep_vertbar (dat, _obj->name)) \
1634 _flag &= ~0x10; \
1635 VALUE_RC (_flag, 70); \
1636 } \
1637 else if (strEQc (#acdbname, "Block") && dat->version >= R_2000) \
1638 ; /* skip 70 for AcDbBlockTableRecord here. done in AcDbBlockBegin */ \
1639 else \
1640 { \
1641 /* mask off 64, the loaded bit 6 */ \
1642 VALUE_RC (_obj->flag & ~64, 70); \
1643 }
1644
1645 // unused
1646 #define LAYER_TABLE_FLAGS(acdbname) \
1647 SINCE (R_13) \
1648 { \
1649 VALUE_TV ("AcDbSymbolTableRecord", 100); \
1650 VALUE_TV ("AcDb" #acdbname "TableRecord", 100); \
1651 } \
1652 if (_obj->name) \
1653 dxf_cvt_tablerecord (dat, obj, _obj->name, 2); \
1654 FIELD_RS (flag, 70)
1655
1656 #include "dwg.spec"
1657
1658 /* This was previously in encode, but since out_dxf needs it for r2013+ 3DSOLIDs
1659 and --disable-write is still an option, we need to move it here.
1660 A global acis_data_idx is needed, since encr_acis_data is split into blocks, but
1661 acis_data is a single stream, so we need to keep track of the current position.
1662 */
1663 EXPORT char *
dwg_encrypt_SAT1(BITCODE_BL blocksize,BITCODE_RC * restrict acis_data,int * restrict acis_data_idx)1664 dwg_encrypt_SAT1 (BITCODE_BL blocksize, BITCODE_RC *restrict acis_data,
1665 int *restrict acis_data_idx)
1666 {
1667 BITCODE_RC* encr_sat_data = (BITCODE_RC*)calloc (blocksize + 1, 1);
1668 int i;
1669 for (i = 0; i < (int)blocksize; i++)
1670 {
1671 if (acis_data[i] <= 32)
1672 encr_sat_data[i] = acis_data[i];
1673 else
1674 encr_sat_data[i] = 159 - acis_data[i];
1675 }
1676 *acis_data_idx = i;
1677 return (char*)encr_sat_data;
1678 }
1679
1680 static int
new_encr_sat_data_line(Dwg_Entity_3DSOLID * restrict _obj,Bit_Chain * dest,unsigned int i)1681 new_encr_sat_data_line (Dwg_Entity_3DSOLID *restrict _obj,Bit_Chain *dest,
1682 unsigned int i)
1683 {
1684 /*
1685 if (i + 1 >= _obj->num_blocks)
1686 {
1687 _obj->encr_sat_data = realloc (_obj->encr_sat_data, (i + 2) * sizeof (char*));
1688 _obj->block_size = realloc (_obj->block_size, (i + 2) * sizeof (BITCODE_BL));
1689 _obj->num_blocks = i + 1;
1690 }
1691 _obj->encr_sat_data[i] = calloc (dest->byte + 2, 1); // fresh, the dest buf is too large
1692 bit_write_TF (dest, (BITCODE_TF) "\n\000", 2); // ensure proper eol, dxf out relies on that.
1693 memcpy (_obj->encr_sat_data[i], dest->chain, dest->byte);
1694 _obj->block_size[i] = dest->byte - 1; // dont count the final 0
1695 bit_set_position (dest, 0);
1696 i++;
1697 */
1698 bit_write_TF (dest, (BITCODE_TF) "\n", 1); // ensure proper eol, dxf out relies on that
1699 return i;
1700 }
1701
1702 // TODO SAT_enum
1703
1704 // logical values are class-specific, and must be strings.
1705 static const char*
SAT_boolean(const char * act_record,bool value)1706 SAT_boolean (const char *act_record, bool value)
1707 {
1708 static int argc = 0;
1709 if (!strEQc (act_record, "varblendsplsur") &&
1710 !strEQc (act_record, "face") &&
1711 !strEQc (act_record, "bdy_geom"))
1712 argc = 0;
1713
1714 if (strEQc (act_record, "sphere") ||
1715 strEQc (act_record, "plane") ||
1716 strEQc (act_record, "stripc") ||
1717 strEQc (act_record, "torus"))
1718 return !value ? "forward_v" : "reverse_v";
1719 else if (strEQc (act_record, "spline") ||
1720 strEQc (act_record, "edge") ||
1721 strEQc (act_record, "meshsurf") ||
1722 strEQc (act_record, "pcurve") ||
1723 strEQc (act_record, "intcurve"))
1724 return !value ? "forward" : "reversed";
1725 else if (strEQc (act_record, "surfcur") ||
1726 strEQc (act_record, "bldcur") ||
1727 strEQc (act_record, "parcur") ||
1728 strEQc (act_record, "projcur") ||
1729 strEQc (act_record, "perspsil"))
1730 return !value ? "surf2" : "surf1";
1731 else if (strEQc (act_record, "sweepsur"))
1732 return !value ? "normal" : "angled";
1733 else if (strEQc (act_record, "var_cross_section"))
1734 return value ? "radius" : "no_radius";
1735 else if (strEQc (act_record, "var_radius"))
1736 return value ? "uncalibrated" : "calibrated";
1737 else if (strEQc (act_record, "wire"))
1738 return value ? "in" : "out";
1739 else if (strEQc (act_record, "adv_var_blend"))
1740 return !value ? "sharp" : "smooth";
1741 else if (strEQc (act_record, "attrib_fhlhead"))
1742 return !value ? "invalid" : "valid";
1743 else if (strEQc (act_record, "attrib_fhlplist") ||
1744 strEQc (act_record, "attrib_fhl_slist"))
1745 return !value ? "invisible" : "visible";
1746 else if (strEQc (act_record, "bl_ent_ent") ||
1747 strEQc (act_record, "bl_inst"))
1748 return !value ? "unset" : "set";
1749
1750 // TODO orthosur undocumented
1751 // now the few classes with mult. locical args
1752 else if (strEQc (act_record, "face"))
1753 {
1754 if (!argc)
1755 {
1756 argc++;
1757 return !value ? "forward" : "reversed";
1758 }
1759 else if (argc == 1)
1760 {
1761 argc++;
1762 return !value ? "single" : "double";
1763 }
1764 else
1765 {
1766 argc = 0;
1767 return !value ? "out" : "in";
1768 }
1769 }
1770 else if (strEQc (act_record, "varblendsplsur"))
1771 {
1772 if (!argc)
1773 {
1774 argc++;
1775 return !value ? "concave" : "convex";
1776 }
1777 else
1778 {
1779 argc = 0;
1780 return !value ? "rb_snapshot" : "rb_envelope";
1781 }
1782 }
1783 else if (strEQc (act_record, "attrib_var_blend"))
1784 {
1785 if (!argc)
1786 {
1787 argc++;
1788 return value ? "uncalibrated" : "calibrated";
1789 }
1790 else if (argc == 1)
1791 {
1792 argc++;
1793 return !value ? "one_radius" : "two_radii";
1794 }
1795 else
1796 {
1797 argc = 0;
1798 return !value ? "forward" : "reversed";
1799 }
1800 }
1801 else if (strEQc (act_record, "bdy_geom"))
1802 {
1803 if (!argc)
1804 {
1805 argc++;
1806 return value ? "non_cross" : "cross";
1807 }
1808 else
1809 {
1810 argc++;
1811 return !value ? "non_smooth" : "smooth";
1812 }
1813 }
1814 else
1815 return value ? "I" : "F";
1816 }
1817
1818 /* Converts v2 SAB acis_data in-place to SAT v1 encr_sat_data[].
1819 Sets dxf_sab_converted to 1, denoting that encr_sat_data is NOT the
1820 encrypted acis_data anymore, rather the converted from SAB for DXF.
1821 */
1822 EXPORT int
dwg_convert_SAB_to_SAT1(Dwg_Entity_3DSOLID * restrict _obj)1823 dwg_convert_SAB_to_SAT1 (Dwg_Entity_3DSOLID *restrict _obj)
1824 {
1825 Bit_Chain dest = { NULL, 0, 0, 0 };
1826 Bit_Chain src = { NULL, 0, 0, 0 };
1827 unsigned int i = 0, num_blocks = 2;
1828 BITCODE_RC c;
1829 char *p = (char*)&_obj->acis_data[15];
1830 //char *end, *dest, *enddest;
1831 long unsigned int size;
1832 BITCODE_RL version, num_records, num_entities, has_history;
1833 //char *product_string, *acis_version, *date;
1834 BITCODE_RD num_mm_units, resabs, resnor;
1835 // Note that r2013+ has ASM data instead.
1836 // const char enddata[] = "\016\003End\016\002of\016\004ACIS\r\004data";
1837 // const char enddata1[] = "\016\003End\016\002of\016\003ASM\r\004data";
1838 int l = 0;
1839 int forward = 0;
1840 int skip_hist = 0;
1841 char act_record [80];
1842 int error;
1843 // We need dwg->header.version for the target ACIS version.
1844 const Dwg_Object* obj = dwg_obj_generic_to_object (_obj, &error);
1845 const Dwg_Data *dwg = obj ? obj->parent : NULL;
1846 Dwg_Version_Type dwg_version = dwg ? dwg->header.version : R_2000;
1847 // Hack: For DXF dont write n the AcDs vs format. No history, no ASM, early versions.
1848 #ifndef CAN_ACIS_IN_DS_DATA
1849 if (dwg_version >= R_2013)
1850 dwg_version = R_2004;
1851 #endif
1852
1853 if (_obj->num_blocks)
1854 num_blocks = _obj->num_blocks;
1855 if (!_obj->block_size)
1856 _obj->block_size = calloc (num_blocks, sizeof (BITCODE_BL));
1857 if (!_obj->encr_sat_data)
1858 _obj->encr_sat_data = calloc (num_blocks, sizeof (char *));
1859
1860 _obj->_dxf_sab_converted = 1;
1861 if (!_obj->sab_size)
1862 _obj->sab_size = _obj->block_size[0];
1863 //end = &p[_obj->sab_size];
1864
1865 if (!memBEGINc ((char*)_obj->acis_data, "ACIS BinaryFile"))
1866 {
1867 LOG_ERROR ("acis_data is not a SAB 2 'ACIS BinaryFile'");
1868 _obj->num_blocks = 0;
1869 _obj->encr_sat_data[0] = NULL;
1870 return 1;
1871 }
1872 //dest = &_obj->encr_sat_data[0][0];
1873 //enddest = &dest[size];
1874 bit_chain_alloc (&dest);
1875 src.chain = &_obj->acis_data[15];
1876 src.size = _obj->sab_size - 15;
1877
1878 // header only
1879 #define SAB_RD(key) \
1880 c = bit_read_RC (&src); /* 6 */ \
1881 LOG_HANDLE (#key " [%d] ", c) \
1882 key = bit_read_RD (&src); \
1883 dest.byte += sprintf ((char*)&dest.chain[dest.byte], "%g ", key); \
1884 LOG_TRACE ("%g ", key)
1885 // record variant
1886 #define SAB_RD1() \
1887 { \
1888 double f = bit_read_RD (&src); \
1889 int s; \
1890 if (dest.byte + 16 >= dest.size) \
1891 bit_chain_alloc (&dest); \
1892 if (l + 16 > 255) \
1893 { \
1894 bit_write_TF (&dest, (BITCODE_TF) "\n", 1); \
1895 LOG_TRACE ("Split overlong SAT line\n"); \
1896 l = 0; \
1897 } \
1898 s = sprintf ((char*)&dest.chain[dest.byte], "%g ", f); \
1899 dest.byte += s; l += s; \
1900 LOG_TRACE ("%g ", f); \
1901 }
1902 // key is ignored here. header only
1903 #define SAB_T(key) \
1904 { \
1905 int len, s; \
1906 c = bit_read_RC (&src); \
1907 LOG_HANDLE (#key " [%d] ", c) \
1908 len = bit_read_RC (&src); \
1909 s = sprintf ((char*)&dest.chain[dest.byte], "%d ", len); \
1910 dest.byte += s; l += s; \
1911 LOG_TRACE ("%d %.*s ", len, len, &src.chain[src.byte]); \
1912 bit_write_TF (&dest, &src.chain[src.byte], len); \
1913 bit_write_TF (&dest, (BITCODE_TF) " ", 1); \
1914 l += len + 1; \
1915 src.byte += len; \
1916 }
1917 #define SAB_TF(x) \
1918 if (l + sizeof(x) > 255) \
1919 { \
1920 bit_write_TF (&dest, (BITCODE_TF) "\n", 1); \
1921 LOG_TRACE ("Split overlong SAT line\n"); \
1922 l = 0; \
1923 } \
1924 bit_write_TF (&dest, (BITCODE_TF) x, sizeof (x) - 1); \
1925 bit_write_TF (&dest, (BITCODE_TF) " ", 1); \
1926 l += sizeof (x); \
1927 LOG_TRACE ("%s ", x)
1928 #define SAB_TV(x) \
1929 if (l + strlen (x) > 255) \
1930 { \
1931 bit_write_TF (&dest, (BITCODE_TF) "\n", 1); \
1932 LOG_TRACE ("Split overlong SAT line\n"); \
1933 l = 0; \
1934 } \
1935 bit_write_TF (&dest, (BITCODE_TF) x, strlen (x)); \
1936 bit_write_TF (&dest, (BITCODE_TF) " ", 1); \
1937 l += strlen (x) + 1; \
1938 LOG_TRACE ("%s ", x)
1939
1940 // create the two vectors encr_sat_data[] and block_size[] on the fly from the SAB
1941 // http://paulbourke.net/dataformats/sat/sat.pdf
1942 /* ACIS BinaryFile [64 81 6x0[ [2 7x0]
1943 "\a\020Autodesk AutoCAD\a\024ASM 223.0.1.1930 OSX\a\030Mon Jun 18 11:09:32 2018\006"
1944 6x0 16 63 "\006\215\355\265\240\367ư>" "\006\273\275\327\331\337|\333= "\r\tasmheader" \f\377\377\377\377\004\377\377\377\377\a\f223.0.1.1930\021 \r\004body \f\377\377\377\377\004\377\377\377\377\f\377\377\377\377\f\002"
1945 */
1946 version = bit_read_RL (&src);
1947 num_records = bit_read_RL (&src); // if 0 until end marker. total
1948 num_entities = bit_read_RL (&src); // named top in the ACIS docs
1949 has_history = bit_read_RL (&src); // named as flags in the ACIS docs
1950 LOG_TRACE ("%d %d %d %d \n", version, num_records, num_entities, has_history);
1951 #ifndef CAN_ACIS_HISTORY
1952 if (dwg_version < R_2010)
1953 has_history = 0; // FIXME: need to delete all persubent-acadSolidHistory-attrib lines then.
1954 #endif
1955 if (dwg_version >= R_2013)
1956 version = 21800;
1957 else if (dwg_version >= R_2010)
1958 version = 21500;
1959 else if (dwg_version >= R_2007)
1960 version = 21200;
1961 else if (dwg_version >= R_2004)
1962 version = 20800;
1963 else if (dwg_version >= R_2000)
1964 version = 400;
1965 else if (dwg_version < R_2000)
1966 version = 106;
1967 dest.byte += sprintf ((char*)dest.chain, "%d %d %d %d ", version, num_records,
1968 num_entities, has_history);
1969 LOG_TRACE ("=> %d %d %d %d \n", version, num_records, num_entities, has_history);
1970 i = new_encr_sat_data_line (_obj, &dest, i);
1971
1972 SAB_T (product_string)
1973 SAB_T (acis_version)
1974 SAB_T (date)
1975 i = new_encr_sat_data_line (_obj, &dest, i);
1976 LOG_TRACE ("\n");
1977
1978 SAB_RD (num_mm_units);
1979 SAB_RD (resabs);
1980 SAB_RD (resnor);
1981 i = new_encr_sat_data_line (_obj, &dest, i);
1982 LOG_TRACE ("\n");
1983
1984 c = bit_read_RC (&src); // type tag
1985 while (src.byte < src.size)
1986 {
1987 LOG_HANDLE ("[%d] ", c)
1988 switch (c)
1989 {
1990 // check size, realloc encr_sat_data[i], set dest
1991 case 17: // # end of record
1992 forward = 0;
1993 if (dest.byte + 2 >= dest.size)
1994 bit_chain_alloc (&dest);
1995 if (skip_hist && !has_history)
1996 {
1997 // delete any persubent-acadSolidHistory-attrib line
1998 char *s = strrchr ((char*)dest.chain, '#');
1999 int diff = s ? (char*)&dest.chain[dest.byte] - s : 0;
2000 if (diff > 0 && dest.chain[dest.byte - diff + 1] == '\n')
2001 {
2002 dest.byte -= (diff - 2);
2003 }
2004 LOG_TRACE ("# --deleted--\n");
2005 }
2006 else
2007 {
2008 int s = sprintf ((char*)&dest.chain[dest.byte], "#\n");
2009 dest.byte += s; l += s;
2010 LOG_TRACE ("#\n");
2011 }
2012 //i = new_encr_sat_data_line (_obj, &dest, i);
2013 l = 0;
2014 skip_hist = 0;
2015 break;
2016 case 13: // ident
2017 _obj->encr_sat_data[i] = (char*)dest.chain;
2018 // fallthru
2019 case 7: // char len
2020 case 14: // subident
2021 {
2022 int len = bit_read_RC (&src);
2023 if (dest.byte + len + 4 >= dest.size)
2024 bit_chain_alloc (&dest);
2025 if (c == 7 && i < 3)
2026 {
2027 int s = sprintf ((char*)&dest.chain[dest.byte], "%d ", len);
2028 dest.byte += s; l += s;
2029 LOG_TRACE ("%d ", len);
2030 }
2031 LOG_TRACE ("%.*s%s", len, &src.chain[src.byte], c == 14 ? "-" : " ");
2032 #ifndef CAN_ACIS_IN_DS_DATA
2033 // fixup End-of-ASM-data => End-of-ACIS-data if >= r2013
2034 // downconvert ASM (AcDs) to ACIS for DXF
2035 if (len == 3 && c == 14 && !memcmp (&src.chain[src.byte], "ASM", 3))
2036 {
2037 LOG_TRACE ("=>ACIS-");
2038 skip_hist = 1;
2039 bit_write_TF (&dest, (BITCODE_TF)"ACIS", 4);
2040 }
2041 else
2042 #endif
2043 bit_write_TF (&dest, &src.chain[src.byte], len);
2044 #ifndef CAN_ACIS_HISTORY
2045 if (c == 14 && len == strlen ("acadSolidHistory") &&
2046 !memcmp (&src.chain[src.byte], "acadSolidHistory", len))
2047 {
2048 skip_hist = 1; // skip the whole line
2049 }
2050 #endif
2051 if (c == 13 && len < 80)
2052 {
2053 memcpy (act_record, &src.chain[src.byte], len);
2054 act_record[len] = '\0'; // to find identifier-specific true/false strings
2055 }
2056 // TODO Begin-of-ACIS-History-Data => new line
2057 // TODO End-of-ACIS-History-Section => new line
2058 //if (has_history && c == 13 && len = 4 && memBEGINc (&src.chain[src.byte], "Data"))
2059 // i = new_encr_sat_data_line (_obj, &dest, i);
2060 src.byte += len;
2061 if (c == 14)
2062 bit_write_TF (&dest, (BITCODE_TF)"-", 1);
2063 else
2064 bit_write_TF (&dest, (BITCODE_TF)" ", 1);
2065 l++;
2066 break;
2067 }
2068 case 8: // short len
2069 {
2070 int len = bit_read_RS (&src);
2071 if (src.byte + len >= src.size)
2072 {
2073 LOG_ERROR ("Invalid SAB");
2074 bit_chain_free (&dest);
2075 _obj->num_blocks = 0;
2076 _obj->encr_sat_data[0] = NULL;
2077 return 1;
2078 }
2079 if (dest.byte + len + 1 >= dest.size)
2080 bit_chain_alloc (&dest);
2081 LOG_TRACE ("%.*s%s", len, &src.chain[src.byte], " ")
2082 bit_write_TF (&dest, &src.chain[src.byte], len);
2083 src.byte += len;
2084 bit_write_TF (&dest, (BITCODE_TF)" ", 1);
2085 l += len + 1;
2086 break;
2087 }
2088 case 9: // long len
2089 {
2090 int len = bit_read_RL (&src);
2091 if (src.byte + len >= src.size)
2092 {
2093 LOG_ERROR ("Invalid SAB");
2094 bit_chain_free (&dest);
2095 _obj->num_blocks = 0;
2096 _obj->encr_sat_data[0] = NULL;
2097 return 1;
2098 }
2099 if (dest.byte + len + 1 >= dest.size)
2100 bit_chain_alloc (&dest);
2101 if (l + len > 255)
2102 {
2103 bit_write_TF (&dest, (BITCODE_TF) "\n", 1);
2104 LOG_TRACE ("Split overlong SAT line\n");
2105 l = 0;
2106 }
2107 LOG_TRACE ("%.*s%s", len, &src.chain[src.byte], " ")
2108 bit_write_TF (&dest, &src.chain[src.byte], len);
2109 src.byte += len;
2110 bit_write_TF (&dest, (BITCODE_TF)" ", 1);
2111 l += len + 1;
2112 break;
2113 }
2114 case 10: // 0 byte TRUE
2115 {
2116 const char *s = SAT_boolean (act_record, 1);
2117 SAB_TV (s);
2118 }
2119 break;
2120 case 11: // 0 byte FALSE
2121 {
2122 const char *s = SAT_boolean (act_record, 0);
2123 SAB_TV (s);
2124 }
2125 break;
2126 case 15: // 0 byte subtype start
2127 SAB_TF ("{");
2128 break;
2129 case 16: // 1 byte subtype end
2130 SAB_TF ("}");
2131 LOG_HANDLE ("[%c] ", src.chain[src.byte]);
2132 //src.byte++;
2133 break;
2134 case 2: // char constant
2135 {
2136 int s;
2137 int8_t ll = (int8_t)bit_read_RC (&src);
2138 if (dest.byte + 4 >= dest.size)
2139 bit_chain_alloc (&dest);
2140 if (l + 3 > 255)
2141 {
2142 bit_write_TF (&dest, (BITCODE_TF) "\n", 1);
2143 LOG_TRACE ("Split overlong SAT line\n");
2144 l = 0;
2145 }
2146 s = sprintf ((char*)&dest.chain[dest.byte], "%" PRId8 " ", ll);
2147 dest.byte += s; l += s;
2148 LOG_TRACE ("%" PRId8 " ", ll)
2149 }
2150 break;
2151 case 3: // short constant
2152 {
2153 int s;
2154 int16_t ll = (int16_t)bit_read_RS (&src);
2155 if (dest.byte + 8 >= dest.size)
2156 bit_chain_alloc (&dest);
2157 s = sprintf ((char*)&dest.chain[dest.byte], "%" PRId16 " ", ll);
2158 dest.byte += s; l += s;
2159 LOG_TRACE ("%" PRId16 " ", ll)
2160 }
2161 break;
2162 case 4: // long constant
2163 case 21: // enum value. See GH jmplonka/InventorLoader:Acis.py
2164 {
2165 int s;
2166 BITCODE_RLd ll = (BITCODE_RLd)bit_read_RL (&src);
2167 if (dest.byte + 16 >= dest.size)
2168 bit_chain_alloc (&dest);
2169 s = sprintf ((char*)&dest.chain[dest.byte], "$%" PRId32 " ", ll);
2170 dest.byte += s; l += s;
2171 LOG_TRACE ("$%" PRId32 " ", ll)
2172 }
2173 break;
2174 case 5: // float constant
2175 {
2176 int s;
2177 float f = bit_read_RL (&src);
2178 if (dest.byte + 16 >= dest.size)
2179 bit_chain_alloc (&dest);
2180 if (l + 16 > 255)
2181 {
2182 bit_write_TF (&dest, (BITCODE_TF) "\n", 1);
2183 LOG_TRACE ("Split overlong SAT line\n");
2184 l = 0;
2185 }
2186 s = sprintf ((char*)&dest.chain[dest.byte], "%g ", (double)f);
2187 dest.byte += s; l += s;
2188 LOG_TRACE ("%g ", (double)f)
2189 }
2190 break;
2191 case 12: // 4 byte pointer index
2192 {
2193 int s;
2194 BITCODE_RLd ll = (BITCODE_RLd)bit_read_RL (&src);
2195 if (dest.byte + 16 >= dest.size)
2196 bit_chain_alloc (&dest);
2197 if (l + 6 > 255)
2198 {
2199 bit_write_TF (&dest, (BITCODE_TF) "\n", 1);
2200 LOG_TRACE ("Split overlong SAT line\n");
2201 l = 0;
2202 }
2203 s = sprintf ((char*)&dest.chain[dest.byte], "$%" PRId32 " ", ll);
2204 dest.byte += s; l += s;
2205 LOG_TRACE ("$%" PRId32 " ", ll)
2206 }
2207 break;
2208 case 19: // 3x double-float position
2209 case 20: // 3x double-float vector
2210 SAB_RD1();
2211 SAB_RD1();
2212 // fallthru
2213 case 6: // 8 byte double-float, e.g. in the 2nd header line
2214 SAB_RD1();
2215 break;
2216 //case 22: // U-V-Vector
2217 // break;
2218 case 23: // int64
2219 {
2220 int s;
2221 int64_t i64 = (int64_t)bit_read_RLL (&src);
2222 if (dest.byte + 16 >= dest.size)
2223 bit_chain_alloc (&dest);
2224 if (l + 16 > 255)
2225 {
2226 bit_write_TF (&dest, (BITCODE_TF) "\n", 1);
2227 LOG_TRACE ("Split overlong SAT line\n");
2228 l = 0;
2229 }
2230 s = sprintf ((char*)&dest.chain[dest.byte], "$%" PRId64 " ", i64);
2231 dest.byte += s; l += s;
2232 LOG_TRACE ("$%" PRId64 " ", i64)
2233 }
2234 break;
2235 default:
2236 LOG_ERROR ("Unknown SAB tag %d", c);
2237 }
2238 c = bit_read_RC (&src);
2239 }
2240
2241 //if (c != 17) // last line didn't end with #, but End-of-ACIS-data or End-of-ASM-data
2242 // i = new_encr_sat_data_line (_obj, &dest, i);
2243 num_blocks = _obj->num_blocks = 1;
2244 // Nope, keep it. Teigha always adds it, ASM not.
2245 //if (strEQc((char*)&dest.chain[dest.byte-17], "End-of-ACIS-data "))
2246 // dest.byte -= 17;
2247 bit_write_TF (&dest, (BITCODE_TF)"\n", 1);
2248 size = dest.byte; // total size
2249 {
2250 unsigned long off = 0;
2251 while (size > 4096)
2252 { // chunks of 4096
2253 if (i >= num_blocks) {
2254 _obj->block_size = realloc (_obj->block_size, (i + 2) * sizeof (BITCODE_BL));
2255 _obj->encr_sat_data = realloc (_obj->encr_sat_data, (i + 1) * sizeof (char**));
2256 num_blocks = i + 1;
2257 }
2258 _obj->encr_sat_data[i] = calloc (4096, 1);
2259 memcpy (_obj->encr_sat_data[i], &dest.chain[off], 4096);
2260 _obj->block_size[i] = 4096;
2261 LOG_TRACE ("block_size[%d] = 4096\n", i);
2262 i++;
2263 size -= 4096;
2264 off += 4096;
2265 }
2266 // and the smaller rest
2267 if (i >= num_blocks) {
2268 _obj->block_size = realloc (_obj->block_size, (i + 2) * sizeof (BITCODE_BL));
2269 _obj->encr_sat_data = realloc (_obj->encr_sat_data, (i + 1) * sizeof (char**));
2270 num_blocks = i + 1;
2271 }
2272 _obj->encr_sat_data[i] = calloc (size + 1, 1); // shrink it
2273 memcpy (_obj->encr_sat_data[i], &dest.chain[off], size);
2274 _obj->block_size[i] = size;
2275 LOG_TRACE ("block_size[%d] = %lu\n", i, size);
2276 }
2277 bit_chain_free (&dest);
2278 LOG_TRACE ("\n");
2279 _obj->acis_empty = 0;
2280 _obj->version = 1; // conversion complete
2281
2282 if (i + 2 >= num_blocks)
2283 _obj->block_size = realloc (_obj->block_size, (i + 2) * sizeof (BITCODE_BL));
2284 _obj->num_blocks = i;
2285 _obj->block_size[i + 1] = 0;
2286 return 0;
2287 }
2288
2289 /* Add history_id for old version 1 SAT if there's one */
2290 static void
dxf_check_history_id(Bit_Chain * restrict dat,const Dwg_Object * restrict obj,Dwg_Entity_3DSOLID * restrict _obj)2291 dxf_check_history_id (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
2292 Dwg_Entity_3DSOLID *restrict _obj)
2293 {
2294 if (!_obj->history_id || !_obj->history_id->absolute_ref)
2295 {
2296 Dwg_Data *dwg = obj->parent;
2297 Dwg_Handle *hdl = NULL;
2298 if (_obj->history_id)
2299 { /* Avoid NULL HDL */
2300 Dwg_Object *o = dwg_ref_object (dwg, _obj->history_id);
2301 if (o)
2302 hdl = &o->handle;
2303 }
2304 if (!hdl)
2305 /* FIXME Just take the first HISTORY_CLASS
2306 TODO Check HISTORY_CLASS.owner (2, 360) */
2307 hdl = dwg_find_first_type_handle (dwg, DWG_TYPE_ACSH_HISTORY_CLASS);
2308 if (hdl)
2309 _obj->history_id = dwg_add_handleref (dwg, 4, hdl->value, obj);
2310 if (_obj->history_id)
2311 LOG_TRACE ("Empty %s.history_id => " FORMAT_REF "\n", obj->name,
2312 ARGS_REF (_obj->history_id))
2313 else
2314 LOG_WARN ("Empty %s.history_id\n", obj->name)
2315 }
2316 }
2317
2318 static int
dxf_3dsolid(Bit_Chain * restrict dat,const Dwg_Object * restrict obj,Dwg_Entity_3DSOLID * restrict _obj)2319 dxf_3dsolid (Bit_Chain *restrict dat, const Dwg_Object *restrict obj,
2320 Dwg_Entity_3DSOLID *restrict _obj)
2321 {
2322 BITCODE_BL i;
2323 int error = 0;
2324
2325 COMMON_ENTITY_HANDLE_DATA;
2326 FIELD_B0 (acis_empty, 290);
2327 if (!FIELD_VALUE (acis_empty))
2328 {
2329 FIELD_B (unknown, 0);
2330 if (FIELD_VALUE (version) == 2)
2331 {
2332 BITCODE_RC *acis_data;
2333 LOG_TRACE ("Convert SAB ACIS BinaryFile v2 to encrypted SAT v1\n");
2334 error |= dwg_convert_SAB_to_SAT1 (_obj);
2335
2336 for (i = 0; i < FIELD_VALUE (num_blocks); i++)
2337 {
2338 int idx = 0; // here idx is just local, always starting at 0. ignored
2339 char *ptr = dwg_encrypt_SAT1 (
2340 _obj->block_size[i], (BITCODE_RC *)_obj->encr_sat_data[i],
2341 &idx);
2342
2343 free (_obj->encr_sat_data[i]);
2344 _obj->encr_sat_data[i] = ptr;
2345 }
2346 _obj->version = 1; // conversion complete
2347 }
2348 FIELD_BS (version, 70); // always 1
2349 for (i = 0; i < FIELD_VALUE (num_blocks); i++)
2350 {
2351 char *s = FIELD_VALUE (encr_sat_data[i]);
2352 // FIXME
2353 // only DXF 1, always keep len <255
2354 //int len = _obj->_dxf_sab_converted ? FIELD_VALUE (block_size[i]) : strlen (s);
2355 int len = FIELD_VALUE (block_size[i]);
2356 while (len > 0)
2357 {
2358 char *n = strchr (s, '\n');
2359 int l = len > 255 ? 255 : len;
2360 char *caret = strchr (s, '^');
2361 if (n && (n - s < len))
2362 {
2363 l = n - s;
2364 }
2365 if (l)
2366 {
2367 GROUP (1);
2368 // replace "^" by "^ "
2369 while (caret && caret < n)
2370 {
2371 int lc = caret - s;
2372 fprintf (dat->fh, "%.*s^ ", lc, s);
2373 lc++;
2374 l -= lc;
2375 len -= lc;
2376 s += lc;
2377 caret = l > 1 ? strchr (s, '^') : NULL;
2378 }
2379 if (l > 255)
2380 LOG_ERROR ("Overlong SAT line \"%s\" len=%d", s, l)
2381 if (s[l - 1] == '\r')
2382 fprintf (dat->fh, "%.*s\n", l, s);
2383 else
2384 fprintf (dat->fh, "%.*s\r\n", l, s);
2385 l++;
2386 len -= l;
2387 s += l;
2388 }
2389 else
2390 {
2391 len--;
2392 s++;
2393 }
2394 }
2395 }
2396 }
2397 dxf_check_history_id (dat, obj, _obj);
2398 // the rest is done in COMMON_3DSOLID in the spec.
2399 return error;
2400 }
2401
2402 /* returns 0 on success
2403 */
2404 static int
dwg_dxf_variable_type(const Dwg_Data * restrict dwg,Bit_Chain * restrict dat,Dwg_Object * restrict obj)2405 dwg_dxf_variable_type (const Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
2406 Dwg_Object *restrict obj)
2407 {
2408 int i;
2409 Dwg_Class *klass;
2410 int is_entity;
2411
2412 i = obj->type - 500;
2413 if (i < 0 || i >= dwg->num_classes)
2414 return DWG_ERR_INVALIDTYPE;
2415
2416 klass = &dwg->dwg_class[i];
2417 if (!klass || !klass->dxfname)
2418 return DWG_ERR_INTERNALERROR;
2419 is_entity = dwg_class_is_entity (klass);
2420 if (dat->version < R_2000)
2421 {
2422 // keep only: IMAGE, LWPOLYLINE, HATCH
2423 if (is_entity &&
2424 strNE (klass->dxfname, "IMAGE") &&
2425 strNEc (klass->dxfname, "LWPOLYLINE") &&
2426 strNEc (klass->dxfname, "HATCH"))
2427 {
2428 LOG_WARN ("Skip %s\n", klass->dxfname)
2429 return DWG_ERR_UNHANDLEDCLASS;
2430 }
2431 // keep only: DICTIONARYVAR, MATERIAL, RASTERVARIABLES, IMAGEDEF_REACTOR, XRECORD, IDBUFFER
2432 else if (!is_entity &&
2433 strNEc (klass->dxfname, "DICTIONARYVAR") &&
2434 strNEc (klass->dxfname, "MATERIAL") &&
2435 strNEc (klass->dxfname, "RASTERVARIABLES") &&
2436 strNEc (klass->dxfname, "IDBUFFER") &&
2437 strNEc (klass->dxfname, "IMAGEDEF_REACTOR") &&
2438 strNEc (klass->dxfname, "XRECORD"))
2439 {
2440 LOG_WARN ("Skip %s\n", klass->dxfname)
2441 return DWG_ERR_UNHANDLEDCLASS;
2442 }
2443 }
2444
2445 // if (!is_entity)
2446 // fprintf(dat->fh, " 0\r\n%s\r\n", dxfname);
2447
2448 // clang-format off
2449 #include "classes.inc"
2450 // clang-format on
2451
2452 return DWG_ERR_UNHANDLEDCLASS;
2453 }
2454
2455 /* process unsorted vertices until SEQEND */
2456 #define decl_dxf_process_VERTEX(token) \
2457 static int dxf_process_VERTEX_##token (Bit_Chain *restrict dat, \
2458 const Dwg_Object *restrict obj, \
2459 int *restrict i) \
2460 { \
2461 int error = 0; \
2462 Dwg_Entity_POLYLINE_##token *_obj \
2463 = obj->tio.entity->tio.POLYLINE_##token; \
2464 \
2465 VERSIONS (R_13, R_2000) \
2466 { \
2467 Dwg_Object *last_vertex = _obj->last_vertex ? _obj->last_vertex->obj : NULL; \
2468 Dwg_Object *o = _obj->first_vertex ? _obj->first_vertex->obj : NULL; \
2469 if (!o || !last_vertex) \
2470 return DWG_ERR_INVALIDHANDLE; \
2471 if (o->fixedtype == DWG_TYPE_VERTEX_##token) \
2472 error |= dwg_dxf_VERTEX_##token (dat, o); \
2473 *i = *i + 1; \
2474 do \
2475 { \
2476 o = dwg_next_object (o); \
2477 if (!o) \
2478 return DWG_ERR_INVALIDHANDLE; \
2479 if (strEQc (#token, "PFACE") \
2480 && o->fixedtype == DWG_TYPE_VERTEX_PFACE_FACE) \
2481 { \
2482 error |= dwg_dxf_VERTEX_PFACE_FACE (dat, o); \
2483 } \
2484 else if (o->fixedtype == DWG_TYPE_VERTEX_##token) \
2485 { \
2486 error |= dwg_dxf_VERTEX_##token (dat, o); \
2487 } \
2488 *i = *i + 1; \
2489 } \
2490 while (o->fixedtype != DWG_TYPE_SEQEND && o != last_vertex); \
2491 o = _obj->seqend ? _obj->seqend->obj : NULL; \
2492 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
2493 error |= dwg_dxf_SEQEND (dat, o); \
2494 *i = *i + 1; \
2495 } \
2496 SINCE (R_2004) \
2497 { \
2498 Dwg_Object *o; \
2499 for (BITCODE_BL j = 0; j < _obj->num_owned; j++) \
2500 { \
2501 o = _obj->vertex && _obj->vertex[j] ? _obj->vertex[j]->obj : NULL; \
2502 if (strEQc (#token, "PFACE") && o \
2503 && o->fixedtype == DWG_TYPE_VERTEX_PFACE_FACE) \
2504 { \
2505 error |= dwg_dxf_VERTEX_PFACE_FACE (dat, o); \
2506 } \
2507 else if (o && o->fixedtype == DWG_TYPE_VERTEX_##token) \
2508 { \
2509 error |= dwg_dxf_VERTEX_##token (dat, o); \
2510 } \
2511 } \
2512 o = _obj->seqend ? _obj->seqend->obj : NULL; \
2513 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
2514 error |= dwg_dxf_SEQEND (dat, o); \
2515 *i = *i + _obj->num_owned + 1; \
2516 } \
2517 return error; \
2518 }
2519
2520 // clang-format off
2521 decl_dxf_process_VERTEX (2D)
2522 decl_dxf_process_VERTEX (3D)
decl_dxf_process_VERTEX(MESH)2523 decl_dxf_process_VERTEX (MESH)
2524 decl_dxf_process_VERTEX (PFACE)
2525 // clang-format on
2526
2527 /* process if seqend before attribs */
2528 #define decl_dxf_process_INSERT(token) \
2529 static int dxf_process_##token (Bit_Chain *restrict dat, \
2530 const Dwg_Object *restrict obj, \
2531 int *restrict i) \
2532 { \
2533 int error = 0; \
2534 Dwg_Entity_##token *_obj = obj->tio.entity->tio.token; \
2535 \
2536 if (!_obj->has_attribs) \
2537 return 0; \
2538 VERSIONS (R_13, R_2000) \
2539 { \
2540 Dwg_Object *last_attrib \
2541 = _obj->last_attrib ? _obj->last_attrib->obj : NULL; \
2542 Dwg_Object *o = _obj->first_attrib ? _obj->first_attrib->obj : NULL; \
2543 if (!o || !last_attrib) \
2544 return DWG_ERR_INVALIDHANDLE; \
2545 if (o->fixedtype == DWG_TYPE_ATTRIB) \
2546 error |= dwg_dxf_ATTRIB (dat, o); \
2547 *i = *i + 1; \
2548 do \
2549 { \
2550 o = dwg_next_object (o); \
2551 if (!o) \
2552 return DWG_ERR_INVALIDHANDLE; \
2553 if (o->fixedtype == DWG_TYPE_ATTRIB) \
2554 error |= dwg_dxf_ATTRIB (dat, o); \
2555 *i = *i + 1; \
2556 } \
2557 while (o->fixedtype == DWG_TYPE_ATTRIB && o != last_attrib); \
2558 o = _obj->seqend ? _obj->seqend->obj : NULL; \
2559 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
2560 error |= dwg_dxf_SEQEND (dat, o); \
2561 *i = *i + 1; \
2562 } \
2563 SINCE (R_2004) \
2564 { \
2565 Dwg_Object *o; \
2566 for (BITCODE_BL j = 0; j < _obj->num_owned; j++) \
2567 { \
2568 o = _obj->attribs && _obj->attribs[j] \
2569 ? _obj->attribs[j]->obj \
2570 : NULL; \
2571 if (o && o->fixedtype == DWG_TYPE_ATTRIB) \
2572 error |= dwg_dxf_ATTRIB (dat, o); \
2573 } \
2574 o = _obj->seqend ? _obj->seqend->obj : NULL; \
2575 if (o && o->fixedtype == DWG_TYPE_SEQEND) \
2576 error |= dwg_dxf_SEQEND (dat, o); \
2577 *i = *i + _obj->num_owned + 1; \
2578 } \
2579 return error; \
2580 }
2581
2582 // clang-format off
2583 decl_dxf_process_INSERT (INSERT)
2584 decl_dxf_process_INSERT (MINSERT)
2585 // clang-format on
2586
2587 static int dwg_dxf_object (Bit_Chain *restrict dat,
2588 const Dwg_Object *restrict obj,
2589 int *restrict i)
2590 {
2591 int error = 0;
2592 int minimal;
2593
2594 if (!obj || !obj->parent)
2595 return DWG_ERR_INTERNALERROR;
2596 minimal = obj->parent->opts & DWG_OPTS_MINIMAL;
2597
2598 switch (obj->type)
2599 {
2600 case DWG_TYPE_TEXT:
2601 return dwg_dxf_TEXT (dat, obj);
2602 case DWG_TYPE_ATTDEF:
2603 return dwg_dxf_ATTDEF (dat, obj);
2604 case DWG_TYPE_BLOCK:
2605 return dwg_dxf_BLOCK (dat, obj);
2606 case DWG_TYPE_ENDBLK:
2607 LOG_WARN ("stale %s subentity", obj->dxfname);
2608 return 0; // dwg_dxf_ENDBLK(dat, obj);
2609 case DWG_TYPE_SEQEND:
2610 LOG_WARN ("stale %s subentity", obj->dxfname);
2611 return 0; // dwg_dxf_SEQEND(dat, obj);
2612
2613 case DWG_TYPE_INSERT:
2614 error = dwg_dxf_INSERT (dat, obj);
2615 return error | dxf_process_INSERT (dat, obj, i);
2616 case DWG_TYPE_MINSERT:
2617 error = dwg_dxf_MINSERT (dat, obj);
2618 return error | dxf_process_MINSERT (dat, obj, i);
2619 case DWG_TYPE_POLYLINE_2D:
2620 error = dwg_dxf_POLYLINE_2D (dat, obj);
2621 return error | dxf_process_VERTEX_2D (dat, obj, i);
2622 case DWG_TYPE_POLYLINE_3D:
2623 error = dwg_dxf_POLYLINE_3D (dat, obj);
2624 return error | dxf_process_VERTEX_3D (dat, obj, i);
2625 case DWG_TYPE_POLYLINE_PFACE:
2626 error = dwg_dxf_POLYLINE_PFACE (dat, obj);
2627 return error | dxf_process_VERTEX_PFACE (dat, obj, i);
2628 case DWG_TYPE_POLYLINE_MESH:
2629 error = dwg_dxf_POLYLINE_MESH (dat, obj);
2630 return error | dxf_process_VERTEX_MESH (dat, obj, i);
2631
2632 case DWG_TYPE_ATTRIB:
2633 LOG_WARN ("stale %s subentity", obj->dxfname);
2634 return dwg_dxf_ATTRIB (dat, obj);
2635 case DWG_TYPE_VERTEX_2D:
2636 LOG_WARN ("stale %s subentity", obj->dxfname);
2637 return dwg_dxf_VERTEX_2D (dat, obj);
2638 case DWG_TYPE_VERTEX_3D:
2639 LOG_WARN ("stale %s subentity", obj->dxfname);
2640 return dwg_dxf_VERTEX_3D (dat, obj);
2641 case DWG_TYPE_VERTEX_MESH:
2642 LOG_WARN ("stale %s subentity", obj->dxfname);
2643 return dwg_dxf_VERTEX_MESH (dat, obj);
2644 case DWG_TYPE_VERTEX_PFACE:
2645 LOG_WARN ("stale %s subentity", obj->dxfname);
2646 return dwg_dxf_VERTEX_PFACE (dat, obj);
2647 case DWG_TYPE_VERTEX_PFACE_FACE:
2648 LOG_WARN ("stale %s subentity", obj->dxfname);
2649 return dwg_dxf_VERTEX_PFACE_FACE (dat, obj);
2650
2651 case DWG_TYPE_ARC:
2652 return dwg_dxf_ARC (dat, obj);
2653 case DWG_TYPE_CIRCLE:
2654 return dwg_dxf_CIRCLE (dat, obj);
2655 case DWG_TYPE_LINE:
2656 return dwg_dxf_LINE (dat, obj);
2657 case DWG_TYPE_DIMENSION_ORDINATE:
2658 return dwg_dxf_DIMENSION_ORDINATE (dat, obj);
2659 case DWG_TYPE_DIMENSION_LINEAR:
2660 return dwg_dxf_DIMENSION_LINEAR (dat, obj);
2661 case DWG_TYPE_DIMENSION_ALIGNED:
2662 return dwg_dxf_DIMENSION_ALIGNED (dat, obj);
2663 case DWG_TYPE_DIMENSION_ANG3PT:
2664 return dwg_dxf_DIMENSION_ANG3PT (dat, obj);
2665 case DWG_TYPE_DIMENSION_ANG2LN:
2666 return dwg_dxf_DIMENSION_ANG2LN (dat, obj);
2667 case DWG_TYPE_DIMENSION_RADIUS:
2668 return dwg_dxf_DIMENSION_RADIUS (dat, obj);
2669 case DWG_TYPE_DIMENSION_DIAMETER:
2670 return dwg_dxf_DIMENSION_DIAMETER (dat, obj);
2671 case DWG_TYPE_POINT:
2672 return dwg_dxf_POINT (dat, obj);
2673 case DWG_TYPE__3DFACE:
2674 return dwg_dxf__3DFACE (dat, obj);
2675 case DWG_TYPE_SOLID:
2676 return dwg_dxf_SOLID (dat, obj);
2677 case DWG_TYPE_TRACE:
2678 return dwg_dxf_TRACE (dat, obj);
2679 case DWG_TYPE_SHAPE:
2680 return dwg_dxf_SHAPE (dat, obj);
2681 case DWG_TYPE_VIEWPORT:
2682 return minimal ? 0 : dwg_dxf_VIEWPORT (dat, obj);
2683 case DWG_TYPE_ELLIPSE:
2684 return dwg_dxf_ELLIPSE (dat, obj);
2685 case DWG_TYPE_SPLINE:
2686 return dwg_dxf_SPLINE (dat, obj);
2687 case DWG_TYPE_REGION:
2688 return dwg_dxf_REGION (dat, obj);
2689 case DWG_TYPE__3DSOLID:
2690 return dwg_dxf__3DSOLID (dat, obj);
2691 case DWG_TYPE_BODY:
2692 return dwg_dxf_BODY (dat, obj);
2693 case DWG_TYPE_RAY:
2694 return dwg_dxf_RAY (dat, obj);
2695 case DWG_TYPE_XLINE:
2696 return dwg_dxf_XLINE (dat, obj);
2697 case DWG_TYPE_DICTIONARY:
2698 return minimal ? 0 : dwg_dxf_DICTIONARY (dat, obj);
2699 case DWG_TYPE_MTEXT:
2700 return dwg_dxf_MTEXT (dat, obj);
2701 case DWG_TYPE_LEADER:
2702 return dwg_dxf_LEADER (dat, obj);
2703 case DWG_TYPE_TOLERANCE:
2704 return dwg_dxf_TOLERANCE (dat, obj);
2705 case DWG_TYPE_MLINE:
2706 #if 1 || defined DEBUG_CLASSES
2707 // TODO: looks good, but acad import crashes
2708 return dwg_dxf_MLINE (dat, obj);
2709 #else
2710 LOG_WARN ("Unhandled Entity MLINE in out_dxf %u/%lX", obj->index,
2711 obj->handle.value)
2712 if (0) dwg_dxf_MLINE (dat, obj);
2713 return DWG_ERR_UNHANDLEDCLASS;
2714 #endif
2715 case DWG_TYPE_BLOCK_CONTROL:
2716 case DWG_TYPE_BLOCK_HEADER:
2717 case DWG_TYPE_LAYER_CONTROL:
2718 case DWG_TYPE_LAYER:
2719 case DWG_TYPE_STYLE_CONTROL:
2720 case DWG_TYPE_STYLE:
2721 case DWG_TYPE_LTYPE_CONTROL:
2722 case DWG_TYPE_LTYPE:
2723 case DWG_TYPE_VIEW_CONTROL:
2724 case DWG_TYPE_VIEW:
2725 case DWG_TYPE_UCS_CONTROL:
2726 case DWG_TYPE_UCS:
2727 case DWG_TYPE_VPORT_CONTROL:
2728 case DWG_TYPE_VPORT:
2729 case DWG_TYPE_APPID_CONTROL:
2730 case DWG_TYPE_APPID:
2731 case DWG_TYPE_DIMSTYLE_CONTROL:
2732 case DWG_TYPE_DIMSTYLE:
2733 case DWG_TYPE_VX_CONTROL:
2734 case DWG_TYPE_VX_TABLE_RECORD:
2735 break;
2736 case DWG_TYPE_GROUP:
2737 return dwg_dxf_GROUP (dat, obj);
2738 case DWG_TYPE_MLINESTYLE:
2739 return minimal ? 0 : dwg_dxf_MLINESTYLE (dat, obj);
2740 case DWG_TYPE_OLE2FRAME:
2741 return minimal ? 0 : dwg_dxf_OLE2FRAME (dat, obj);
2742 case DWG_TYPE_DUMMY:
2743 return 0;
2744 case DWG_TYPE_LONG_TRANSACTION:
2745 return minimal ? 0 : dwg_dxf_LONG_TRANSACTION (dat, obj);
2746 case DWG_TYPE_LWPOLYLINE:
2747 return dwg_dxf_LWPOLYLINE (dat, obj);
2748 case DWG_TYPE_HATCH:
2749 return dwg_dxf_HATCH (dat, obj);
2750 case DWG_TYPE_XRECORD:
2751 return minimal ? 0 : dwg_dxf_XRECORD (dat, obj);
2752 case DWG_TYPE_PLACEHOLDER:
2753 return minimal ? 0 : dwg_dxf_PLACEHOLDER (dat, obj);
2754 case DWG_TYPE_PROXY_ENTITY:
2755 // avoid unused warnings
2756 error |= dwg_dxf_PROXY_ENTITY(dat, obj);
2757 return DWG_ERR_UNHANDLEDCLASS;
2758 case DWG_TYPE_OLEFRAME:
2759 return minimal ? 0 : dwg_dxf_OLEFRAME (dat, obj);
2760 case DWG_TYPE_VBA_PROJECT:
2761 return minimal ? 0 : dwg_dxf_VBA_PROJECT (dat, obj);
2762 case DWG_TYPE_LAYOUT:
2763 return minimal ? 0 : dwg_dxf_LAYOUT (dat, obj);
2764 default:
2765 if (obj->type == obj->parent->layout_type)
2766 {
2767 return minimal ? 0 : dwg_dxf_LAYOUT (dat, obj);
2768 }
2769 /* > 500 */
2770 else if ((error
2771 = dwg_dxf_variable_type (obj->parent, dat, (Dwg_Object *)obj))
2772 & DWG_ERR_UNHANDLEDCLASS)
2773 {
2774 Dwg_Data *dwg = obj->parent;
2775 int j = obj->type - 500;
2776 Dwg_Class *klass = NULL;
2777
2778 if (j >= 0 && j < (int)dwg->num_classes)
2779 klass = &dwg->dwg_class[j];
2780 if (!klass)
2781 {
2782 LOG_WARN ("Unknown object, skipping eed/reactors/xdic");
2783 return DWG_ERR_INVALIDTYPE;
2784 }
2785 return error;
2786 }
2787 }
2788 return DWG_ERR_UNHANDLEDCLASS;
2789 }
2790
2791 static int
dxf_common_entity_handle_data(Bit_Chain * restrict dat,const Dwg_Object * restrict obj)2792 dxf_common_entity_handle_data (Bit_Chain *restrict dat,
2793 const Dwg_Object *restrict obj)
2794 {
2795 const Dwg_Data *dwg = obj->parent;
2796 const Dwg_Object_Entity *ent = obj->tio.entity;
2797 const Dwg_Object_Entity *_obj = ent;
2798 int error = 0;
2799 BITCODE_BL vcount = 0;
2800
2801 // clang-format off
2802 #include "common_entity_handle_data.spec"
2803 #include "common_entity_data.spec"
2804 // clang-format on
2805
2806 return error;
2807 }
2808
2809 RETURNS_NONNULL
2810 const char *
dxf_format(int code)2811 dxf_format (int code)
2812 {
2813 if (0 <= code && code < 5)
2814 return "%s";
2815 if (code == 5 || code == -5)
2816 return "%lX";
2817 if (5 < code && code < 10)
2818 return "%s";
2819 if (code < 60)
2820 return DXF_FORMAT_FLT;
2821 if (code < 80)
2822 return "%6i";
2823 if (80 <= code && code <= 99) // BL int32 lgtm [cpp/constant-comparison]
2824 return "%9li";
2825 if (code == 100)
2826 return "%s";
2827 if (code == 102)
2828 return "%s";
2829 if (code == 105)
2830 return "%lX";
2831 if (110 <= code && code <= 149)
2832 return DXF_FORMAT_FLT;
2833 if (160 <= code && code <= 169)
2834 return "%12li";
2835 if (170 <= code && code <= 179)
2836 return "%6i";
2837 if (210 <= code && code <= 239)
2838 return DXF_FORMAT_FLT;
2839 if (270 <= code && code <= 289)
2840 return "%6i";
2841 if (290 <= code && code <= 299)
2842 return "%6i"; // boolean
2843 if (300 <= code && code <= 319)
2844 return "%s";
2845 if (320 <= code && code <= 369)
2846 return "%lX";
2847 if (370 <= code && code <= 389)
2848 return "%6i";
2849 if (390 <= code && code <= 399)
2850 return "%lX";
2851 if (400 <= code && code <= 409)
2852 return "%6i";
2853 if (410 <= code && code <= 419)
2854 return "%s";
2855 if (420 <= code && code <= 429)
2856 return "%9li"; // int32_t
2857 if (430 <= code && code <= 439)
2858 return "%s";
2859 if (440 <= code && code <= 449)
2860 return "%9li"; // int32_t
2861 if (450 <= code && code <= 459)
2862 return "%12li"; // long
2863 if (460 <= code && code <= 469)
2864 return DXF_FORMAT_FLT;
2865 if (470 <= code && code <= 479)
2866 return "%s";
2867 if (480 <= code && code <= 481)
2868 return "%lX";
2869 if (code == 999)
2870 return "%s";
2871 if (1000 <= code && code <= 1009)
2872 return "%s";
2873 if (1010 <= code && code <= 1059)
2874 return DXF_FORMAT_FLT;
2875 if (1060 <= code && code <= 1070)
2876 return "%6i";
2877 if (code == 1071)
2878 return "%9li"; // int32_t
2879 if (code == 1002) // string => RC
2880 return "%6i";
2881 if (code == 1003) // RL layer
2882 return "%9li";
2883 if (code > 1000)
2884 return dxf_format (code - 1000);
2885
2886 return "(unknown code)";
2887 }
2888
2889 /* num => string. for the reverse see in_dxf.c:dxf_fixup_header()
2890 TODO: maybe use a table.
2891 */
2892 RETURNS_NONNULL
2893 const char *
dxf_codepage(int code,Dwg_Data * dwg)2894 dxf_codepage (int code, Dwg_Data *dwg)
2895 {
2896 if (code == 30 || code == 0)
2897 return "ANSI_1252"; // WesternEurope Windows
2898 else if (code == 1)
2899 return "US_ASCII";
2900 else if (code == 2)
2901 return "ISO-8859-1"; // WesternEurope Latin-1
2902 else if (code == 3)
2903 return "ISO-8859-2"; // MiddleEurope Latin-2
2904 else if (code == 4)
2905 return "ISO-8859-3"; // SouthEurope Latin-3
2906 else if (code == 5)
2907 return "ISO-8859-4"; // NorthEurope Latin-4
2908 else if (code == 6)
2909 return "ISO-8859-5"; // Cyrillic
2910 else if (code == 7)
2911 return "ISO-8859-6"; // Arabic
2912 else if (code == 8)
2913 return "ISO-8859-7"; // Greek
2914 else if (code == 9)
2915 return "ISO-8859-8"; // Hebrew
2916 else if (code == 10)
2917 return "ISO-8859-9"; // Turkish Latin-5
2918 else if (code == 11)
2919 return "CP437"; // DOS-US, DOS Latin US
2920 else if (code == 12)
2921 return "CP850"; // WesternEurope DOS
2922 else if (code == 13)
2923 return "CP852"; // CentralEurope DOS
2924 else if (code == 14)
2925 return "CP855"; // Cyrillic DOS
2926 else if (code == 15)
2927 return "CP857"; // Turkish DOS
2928 else if (code == 16)
2929 return "CP860"; // Portuguese DOS
2930 else if (code == 17)
2931 return "CP861"; // Icelandic DOS
2932 else if (code == 18)
2933 return "CP863"; // French DOS
2934 else if (code == 19)
2935 return "CP864"; // Arabic DOS
2936 else if (code == 20)
2937 return "CP865"; // Nordic DOS
2938 else if (code == 21)
2939 return "CP869"; // Greek DOS
2940 else if (code == 22)
2941 return "CP932"; // Japanese Shift JIS DOS
2942 else if (code == 23)
2943 return "MACINTOSH";
2944 else if (code == 24)
2945 return "BIG5"; // Taiwan DOS
2946 else if (code == 25)
2947 return "CP949"; // Korean UnifiedHangulCode DOS
2948 else if (code == 26)
2949 return "JOHAB"; // Korean cp1361 DOS
2950 else if (code == 27)
2951 return "CP866"; // Russian DOS
2952 else if (code == 28)
2953 return "ANSI_1250"; // CentralEurope Windows
2954 else if (code == 29)
2955 return "ANSI_1251"; // Cyrillic Windows
2956 else if (code == 31)
2957 return "GB2312"; // SimplifiedChinese
2958 else if (code == 32)
2959 return "ANSI_1253"; // Greek Windows
2960 else if (code == 33)
2961 return "ANSI_1254"; // Turkish Windows
2962 else if (code == 34)
2963 return "ANSI_1255"; // Hebrew Windows
2964 else if (code == 35)
2965 return "ANSI_1256"; // Arabic Windows
2966 else if (code == 36)
2967 return "ANSI_1257"; // Baltic Windows
2968 else if (code == 37)
2969 return "ANSI_874"; // Thai Windows
2970 else if (code == 38)
2971 return "ANSI_932"; // Japanese Windows
2972 else if (code == 39)
2973 return "ANSI_936"; // gbk UnifiedChinese Windows
2974 else if (code == 40)
2975 return "ANSI_949"; // Korean Windows
2976 else if (code == 41)
2977 return "ANSI_950"; // TradChinese Windows
2978 else if (code == 42)
2979 return "ANSI_1361"; // Korean JOHAB Windows
2980 else if (code == 43)
2981 return "ANSI_1200"; // UTF-16 LE Microsoft
2982 else if (code == 44)
2983 return "ANSI_1258"; // Vietnamese Windows
2984 else if (dwg->header.version >= R_2007)
2985 return "UTF-8"; // dwg internally: UCS-16, for DXF: UTF-8
2986 else
2987 return "";
2988 }
2989
2990 // see
2991 // https://www.autodesk.com/techpubs/autocad/acad2000/dxf/header_section_group_codes_dxf_02.htm
2992 GCC30_DIAG_IGNORE (-Wformat-nonliteral)
2993 AFL_GCC_TOOBIG
2994 static int
dxf_header_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)2995 dxf_header_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
2996 {
2997 Dwg_Header_Variables *_obj = &dwg->header_vars;
2998 Dwg_Object *obj = NULL;
2999 double ms;
3000 const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
3001 const char *codepage = dxf_codepage (dwg->header.codepage, dwg);
3002
3003 if (!*codepage)
3004 {
3005 LOG_WARN ("Unknown codepage %d, assuming ANSI_1252",
3006 dwg->header.codepage);
3007 }
3008
3009 // clang-format off
3010 #include "header_variables_dxf.spec"
3011 // clang-format on
3012
3013 return 0;
3014 }
3015 AFL_GCC_POP
3016
3017 // only called since r2000. but not really needed, unless referenced
3018 static int
dxf_classes_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3019 dxf_classes_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3020 {
3021 BITCODE_BS j;
3022
3023 SECTION (CLASSES);
3024 LOG_TRACE ("num_classes: %u\n", dwg->num_classes);
3025 for (j = 0; j < dwg->num_classes; j++)
3026 {
3027 const char *dxfname = dwg->dwg_class[j].dxfname;
3028 if (!dxfname)
3029 continue;
3030 // some classes are now builtin
3031 if (dat->version >= R_2004
3032 && (strEQc (dxfname, "ACDBPLACEHOLDER")
3033 || strEQc (dxfname, "LAYOUT")))
3034 continue;
3035 if (strEQc (dxfname, "DATATABLE"))
3036 dxfname = "ACDBDATATABLE";
3037 RECORD (CLASS);
3038 VALUE_TV (dxfname, 1);
3039 VALUE_T (dwg->dwg_class[j].cppname, 2);
3040 if (strEQc (dxfname, "SPATIAL_INDEX"))
3041 VALUE_TFF ("AutoCAD 2000", 3) // special-cased for DXF
3042 else
3043 VALUE_T (dwg->dwg_class[j].appname, 3)
3044 VALUE_RL (dwg->dwg_class[j].proxyflag, 90);
3045 SINCE (R_2004) {
3046 VALUE_RL (dwg->dwg_class[j].num_instances, 91);
3047 }
3048 VALUE_RS (dwg->dwg_class[j].is_zombie, 280); // acad: was-a-zombie
3049 // Is-an-entity. 1f2 for entities, 1f3 for objects
3050 VALUE_RS (dwg->dwg_class[j].item_class_id == 0x1F2 ? 1 : 0, 281);
3051 }
3052 ENDSEC ();
3053 return 0;
3054 }
3055
3056 static int
dxf_tables_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3057 dxf_tables_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3058 {
3059 int error = 0;
3060 unsigned int i;
3061 BITCODE_BL vcount;
3062
3063 SECTION (TABLES);
3064 SINCE (R_9c1)
3065 {
3066 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_VPORT_CONTROL);
3067 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.VPORT_CONTROL)
3068 {
3069 Dwg_Object_VPORT_CONTROL *_ctrl = ctrl->tio.object->tio.VPORT_CONTROL;
3070 Dwg_Object *obj = ctrl;
3071 TABLE (VPORT);
3072 // add handle 5 here at first
3073 COMMON_TABLE_CONTROL_FLAGS;
3074 error |= dwg_dxf_VPORT_CONTROL (dat, ctrl);
3075 // TODO how far back can DXF read 1000?
3076 if (dat->version != dat->from_version && dat->from_version >= R_2000)
3077 {
3078 /* if saved from newer version, eg. AC1032: */
3079 VALUE_TV ("ACAD", 1001);
3080 VALUE_TV ("DbSaveVer", 1000);
3081 VALUE_RS (dwg->header.dwg_version, 1071); // so that 69 is R_2018
3082 }
3083 for (i = 0; i < _ctrl->num_entries; i++)
3084 {
3085 if (!_ctrl->entries)
3086 break;
3087 if (!_ctrl->entries[i])
3088 continue;
3089 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3090 if (obj && obj->type == DWG_TYPE_VPORT)
3091 {
3092 // reordered in the DXF: 2,70,10,11,12,13,14,15,16,...
3093 // special-cased in the spec
3094 error |= dwg_dxf_VPORT (dat, obj);
3095 }
3096 }
3097 ENDTAB ();
3098 }
3099 }
3100 {
3101 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_LTYPE_CONTROL);
3102 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.LTYPE_CONTROL)
3103 {
3104 Dwg_Object_LTYPE_CONTROL *_ctrl = ctrl->tio.object->tio.LTYPE_CONTROL;
3105 Dwg_Object *obj = ctrl;
3106 TABLE (LTYPE);
3107 COMMON_TABLE_CONTROL_FLAGS;
3108 error |= dwg_dxf_LTYPE_CONTROL (dat, ctrl);
3109 // first the 2 builtin ltypes: ByBlock, ByLayer
3110 if ((obj = dwg_ref_object (dwg, dwg->header_vars.LTYPE_BYBLOCK))
3111 && obj->type == DWG_TYPE_LTYPE)
3112 {
3113 error |= dwg_dxf_LTYPE (dat, obj);
3114 }
3115 if ((obj = dwg_ref_object (dwg, dwg->header_vars.LTYPE_BYLAYER))
3116 && obj->type == DWG_TYPE_LTYPE)
3117 {
3118 error |= dwg_dxf_LTYPE (dat, obj);
3119 }
3120 // here LTYPE_CONTINUOUS is already included
3121 for (i = 0; i < _ctrl->num_entries; i++)
3122 {
3123 if (!_ctrl->entries)
3124 break;
3125 if (!_ctrl->entries[i])
3126 continue;
3127 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3128 if (obj && obj->type == DWG_TYPE_LTYPE)
3129 {
3130 error |= dwg_dxf_LTYPE (dat, obj);
3131 }
3132 }
3133 ENDTAB ();
3134 }
3135 }
3136 {
3137 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_LAYER_CONTROL);
3138 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.LAYER_CONTROL)
3139 {
3140 Dwg_Object_LAYER_CONTROL *_ctrl = ctrl->tio.object->tio.LAYER_CONTROL;
3141 Dwg_Object *obj = ctrl;
3142 TABLE (LAYER);
3143 COMMON_TABLE_CONTROL_FLAGS;
3144 error |= dwg_dxf_LAYER_CONTROL (dat, ctrl);
3145 for (i = 0; i < _ctrl->num_entries; i++)
3146 {
3147 if (!_ctrl->entries)
3148 break;
3149 if (!_ctrl->entries[i])
3150 continue;
3151 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3152 if (obj && obj->type == DWG_TYPE_LAYER)
3153 error |= dwg_dxf_LAYER (dat, obj);
3154 // else if (obj && obj->type == DWG_TYPE_DICTIONARY)
3155 // error |= dwg_dxf_DICTIONARY(dat, obj);
3156 }
3157 ENDTAB ();
3158 }
3159 }
3160 {
3161 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_STYLE_CONTROL);
3162 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.STYLE_CONTROL)
3163 {
3164 Dwg_Object_STYLE_CONTROL *_ctrl = ctrl->tio.object->tio.STYLE_CONTROL;
3165 Dwg_Object *obj = ctrl;
3166 TABLE (STYLE);
3167 COMMON_TABLE_CONTROL_FLAGS;
3168 error |= dwg_dxf_STYLE_CONTROL (dat, ctrl);
3169 for (i = 0; i < _ctrl->num_entries; i++)
3170 {
3171 if (!_ctrl->entries)
3172 break;
3173 if (!_ctrl->entries[i])
3174 continue;
3175 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3176 if (obj && obj->type == DWG_TYPE_STYLE)
3177 {
3178 error |= dwg_dxf_STYLE (dat, obj);
3179 }
3180 }
3181 ENDTAB ();
3182 }
3183 }
3184 {
3185 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_VIEW_CONTROL);
3186 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.VIEW_CONTROL)
3187 {
3188 Dwg_Object_VIEW_CONTROL *_ctrl = ctrl->tio.object->tio.VIEW_CONTROL;
3189 Dwg_Object *obj = ctrl;
3190 TABLE (VIEW);
3191 COMMON_TABLE_CONTROL_FLAGS;
3192 error |= dwg_dxf_VIEW_CONTROL (dat, ctrl);
3193 for (i = 0; i < _ctrl->num_entries; i++)
3194 {
3195 if (!_ctrl->entries)
3196 break;
3197 if (!_ctrl->entries[i])
3198 continue;
3199 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3200 if (obj && obj->type == DWG_TYPE_VIEW)
3201 error |= dwg_dxf_VIEW (dat, obj);
3202 }
3203 ENDTAB ();
3204 }
3205 }
3206 SINCE (R_9c1)
3207 {
3208 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_UCS_CONTROL);
3209 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.UCS_CONTROL)
3210 {
3211 Dwg_Object_UCS_CONTROL *_ctrl = ctrl->tio.object->tio.UCS_CONTROL;
3212 Dwg_Object *obj = ctrl;
3213 TABLE (UCS);
3214 COMMON_TABLE_CONTROL_FLAGS;
3215 error |= dwg_dxf_UCS_CONTROL (dat, ctrl);
3216 for (i = 0; i < _ctrl->num_entries; i++)
3217 {
3218 if (!_ctrl->entries)
3219 break;
3220 if (!_ctrl->entries[i])
3221 continue;
3222 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3223 if (obj && obj->type == DWG_TYPE_UCS)
3224 {
3225 error |= dwg_dxf_UCS (dat, obj);
3226 }
3227 }
3228 ENDTAB ();
3229 }
3230 }
3231 SINCE (R_10c1)
3232 {
3233 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_APPID_CONTROL);
3234 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.APPID_CONTROL)
3235 {
3236 Dwg_Object_APPID_CONTROL *_ctrl = ctrl->tio.object->tio.APPID_CONTROL;
3237 Dwg_Object *obj = ctrl;
3238 TABLE (APPID);
3239 COMMON_TABLE_CONTROL_FLAGS;
3240 error |= dwg_dxf_APPID_CONTROL (dat, ctrl);
3241 for (i = 0; i < _ctrl->num_entries; i++)
3242 {
3243 if (!_ctrl->entries)
3244 break;
3245 if (!_ctrl->entries[i])
3246 continue;
3247 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3248 if (obj && obj->type == DWG_TYPE_APPID)
3249 {
3250 error |= dwg_dxf_APPID (dat, obj);
3251 }
3252 }
3253 ENDTAB ();
3254 }
3255 }
3256 SINCE (R_10c1)
3257 {
3258 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_DIMSTYLE_CONTROL);
3259 if (ctrl && ctrl->tio.object && ctrl->tio.object->tio.DIMSTYLE_CONTROL)
3260 {
3261 Dwg_Object_DIMSTYLE_CONTROL *_ctrl = ctrl->tio.object->tio.DIMSTYLE_CONTROL;
3262 Dwg_Object *obj = ctrl;
3263 TABLE (DIMSTYLE);
3264 COMMON_TABLE_CONTROL_FLAGS;
3265 error |= dwg_dxf_DIMSTYLE_CONTROL (dat, ctrl);
3266 // ignoring morehandles
3267 for (i = 0; i < _ctrl->num_entries; i++)
3268 {
3269 if (!_ctrl->entries)
3270 break;
3271 if (!_ctrl->entries[i])
3272 continue;
3273 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3274 if (obj && obj->type == DWG_TYPE_DIMSTYLE)
3275 {
3276 error |= dwg_dxf_DIMSTYLE (dat, obj);
3277 }
3278 }
3279 ENDTAB ();
3280 }
3281 }
3282 // fool the warnings. this table is nowhere to be found in the wild. maybe pre-R_11
3283 if (0)
3284 {
3285 Dwg_Object *ctrl = dwg_get_first_object (dwg, DWG_TYPE_VX_CONTROL);
3286 if (ctrl)
3287 {
3288 Dwg_Object_VX_CONTROL *_ctrl = ctrl->tio.object->tio.VX_CONTROL;
3289 Dwg_Object *obj = ctrl;
3290 TABLE (VX);
3291 COMMON_TABLE_CONTROL_FLAGS;
3292 error |= dwg_dxf_VX_CONTROL (dat, ctrl);
3293 for (i = 0; i < _ctrl->num_entries; i++)
3294 {
3295 if (!_ctrl->entries)
3296 break;
3297 if (!_ctrl->entries[i])
3298 continue;
3299 obj = dwg_ref_object (dwg, _ctrl->entries[i]);
3300 if (obj && obj->type == DWG_TYPE_VX_TABLE_RECORD)
3301 {
3302 error |= dwg_dxf_VX_TABLE_RECORD (dat, obj);
3303 }
3304 }
3305 ENDTAB ();
3306 }
3307 }
3308
3309 SINCE (R_12)
3310 {
3311 Dwg_Object *ctrl, *obj;
3312 Dwg_Object_BLOCK_CONTROL *_ctrl = dwg_block_control (dwg);
3313 Dwg_Object_Ref *ref;
3314 Dwg_Object *mspace = NULL, *pspace = NULL;
3315 if (!_ctrl)
3316 {
3317 LOG_ERROR ("BLOCK_CONTROL missing");
3318 return DWG_ERR_INVALIDDWG;
3319 }
3320 ctrl = dwg_obj_generic_to_object (_ctrl, &error);
3321 if (!ctrl || ctrl->fixedtype != DWG_TYPE_BLOCK_CONTROL)
3322 return DWG_ERR_INVALIDDWG;
3323
3324 obj = ctrl;
3325 TABLE (BLOCK_RECORD);
3326 COMMON_TABLE_CONTROL_FLAGS;
3327 error |= dwg_dxf_BLOCK_CONTROL (dat, ctrl);
3328
3329 #if 0 // unordered pspace
3330 for (i = 0; i < dwg->num_objects; i++)
3331 {
3332 Dwg_Object *hdr = &dwg->object[i];
3333 if (hdr && hdr->supertype == DWG_SUPERTYPE_OBJECT
3334 && hdr->type == DWG_TYPE_BLOCK_HEADER)
3335 {
3336 // not necessarily in the same order as DXF, but exhaustive
3337 RECORD (BLOCK_RECORD);
3338 error |= dwg_dxf_BLOCK_HEADER (dat, hdr);
3339 }
3340 }
3341 #else
3342 mspace = dwg_model_space_object (dwg);
3343 if (!mspace)
3344 return DWG_ERR_INVALIDDWG;
3345 RECORD (BLOCK_RECORD);
3346 error |= dwg_dxf_BLOCK_HEADER (dat, mspace);
3347
3348 ref = dwg_paper_space_ref (dwg);
3349 pspace = ref ? dwg_ref_object (dwg, ref) : NULL;
3350 if (pspace)
3351 {
3352 RECORD (BLOCK_RECORD);
3353 error |= dwg_dxf_BLOCK_HEADER (dat, pspace);
3354 }
3355
3356 for (i = 0; i < dwg->block_control.num_entries; i++)
3357 {
3358 if (!dwg->block_control.entries)
3359 break;
3360 if (!dwg->block_control.entries[i])
3361 continue;
3362 obj = dwg_ref_object (dwg, dwg->block_control.entries[i]);
3363 if (obj && obj->type == DWG_TYPE_BLOCK_HEADER
3364 && obj != mspace
3365 && obj != pspace)
3366 {
3367 RECORD (BLOCK_RECORD);
3368 error |= dwg_dxf_BLOCK_HEADER (dat, obj);
3369 }
3370 }
3371 #endif
3372
3373 ENDTAB ();
3374 }
3375 ENDSEC ();
3376 return 0;
3377 }
3378
3379 static void
dxf_ENDBLK_empty(Bit_Chain * restrict dat,const Dwg_Object * restrict hdr)3380 dxf_ENDBLK_empty (Bit_Chain *restrict dat, const Dwg_Object *restrict hdr)
3381 {
3382 // temp. only. not registered in dwg->object[]
3383 Dwg_Object *obj = (Dwg_Object *)calloc (1, sizeof (Dwg_Object));
3384 Dwg_Data *dwg = hdr->parent;
3385 // Dwg_Entity_ENDBLK *_obj;
3386 obj->parent = dwg;
3387 obj->index = dwg->num_objects;
3388 dwg_setup_ENDBLK (obj);
3389 obj->tio.entity->ownerhandle = (BITCODE_H)calloc (1, sizeof (Dwg_Object_Ref));
3390 obj->tio.entity->ownerhandle->obj = (Dwg_Object *)hdr;
3391 obj->tio.entity->ownerhandle->handleref = hdr->handle;
3392 obj->tio.entity->ownerhandle->absolute_ref = hdr->handle.value;
3393 //_obj = obj->tio.entity->tio.ENDBLK;
3394 dwg_dxf_ENDBLK (dat, obj);
3395 free (obj->tio.entity->tio.ENDBLK);
3396 free (obj->tio.entity->ownerhandle);
3397 free (obj->tio.entity);
3398 free (obj);
3399 }
3400
3401 // a BLOCK_HEADER
3402 static int
dxf_block_write(Bit_Chain * restrict dat,const Dwg_Object * restrict hdr,const Dwg_Object * restrict mspace,const Dwg_Object * restrict pspace,int * restrict i)3403 dxf_block_write (Bit_Chain *restrict dat, const Dwg_Object *restrict hdr,
3404 const Dwg_Object *restrict mspace, const Dwg_Object *restrict pspace,
3405 int *restrict i)
3406 {
3407 int error = 0;
3408 const Dwg_Object_BLOCK_HEADER *restrict _hdr
3409 = hdr->tio.object->tio.BLOCK_HEADER;
3410 Dwg_Object *restrict obj = get_first_owned_block (hdr); // BLOCK
3411 Dwg_Object *restrict endblk = NULL;
3412 unsigned long int mspace_ref = mspace ? mspace->handle.value : 0;
3413 unsigned long int pspace_ref = pspace ? pspace->handle.value : 0;
3414
3415 if (obj)
3416 error |= dwg_dxf_object (dat, obj, i);
3417 else
3418 {
3419 SINCE (R_2004)
3420 {
3421 // first_owned_block
3422 if (IS_FROM_TU (dat))
3423 {
3424 char *s = bit_convert_TU ((BITCODE_TU)_hdr->name);
3425 LOG_ERROR ("BLOCK_HEADER %s block_entity[0] missing", s);
3426 free (s);
3427 }
3428 else
3429 LOG_ERROR ("BLOCK_HEADER %s block_entity[0] missing", _hdr->name);
3430 return DWG_ERR_INVALIDDWG;
3431 }
3432 else
3433 LOG_WARN ("BLOCK_HEADER %s block_entity[0] missing", _hdr->name);
3434 }
3435 // Skip all *Model_Space and *Paper_Space entities, esp. new ones: UNDERLAY, MULTILEADER, ...
3436 // They are all under ENTITIES later. But WIPEOUT and VIEWPORT is here.
3437 // Note: the objects may vary (e.g. example_2000), but the index not.
3438 if ((hdr == mspace) || (hdr->index == mspace->index))
3439 obj = NULL;
3440 else if ((hdr == pspace) || (pspace && hdr->index == pspace->index))
3441 obj = NULL;
3442 else
3443 obj = get_first_owned_entity (hdr); // first_entity or entities[0]
3444 while (obj)
3445 {
3446 if (obj->supertype == DWG_SUPERTYPE_ENTITY
3447 && obj->fixedtype != DWG_TYPE_ENDBLK
3448 && obj->tio.entity != NULL
3449 && (obj->tio.entity->entmode != 2 ||
3450 (obj->tio.entity->ownerhandle != NULL
3451 && obj->tio.entity->ownerhandle->absolute_ref != mspace_ref
3452 && obj->tio.entity->ownerhandle->absolute_ref != pspace_ref)))
3453 error |= dwg_dxf_object (dat, obj, i);
3454 obj = get_next_owned_block_entity (hdr, obj); // until last_entity
3455 }
3456 endblk = get_last_owned_block (hdr);
3457 if (endblk)
3458 {
3459 error |= dwg_dxf_ENDBLK (dat, endblk);
3460 LOG_INFO ("\n")
3461 }
3462 else
3463 {
3464 LOG_WARN ("Empty ENDBLK for \"%s\" %lX", _hdr->name,
3465 hdr ? hdr->handle.value : 0);
3466 dxf_ENDBLK_empty (dat, hdr);
3467 LOG_INFO ("\n")
3468 }
3469 return error;
3470 }
3471
3472 static int
dxf_blocks_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3473 dxf_blocks_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3474 {
3475 int error = 0;
3476 int i;
3477 Dwg_Object *restrict mspace = dwg_model_space_object (dwg);
3478 Dwg_Object *restrict pspace = dwg_paper_space_object (dwg);
3479
3480 if (!mspace)
3481 return DWG_ERR_UNHANDLEDCLASS;
3482
3483 // If there's no *Model_Space block skip this BLOCKS section.
3484 // Or try handle 1F with r2000+, 17 with r14
3485 // obj = get_first_owned_block(hdr);
3486 // if (!obj)
3487 // obj = dwg_resolve_handle(dwg, dwg->header.version >= R_2000 ? 0x1f :
3488 // 0x17);
3489 // if (!obj)
3490 // return 1;
3491
3492 SECTION (BLOCKS);
3493 /* There may be unconnected pspace blocks (not caught by above),
3494 such as pspace referred by a LAYOUT or DIMENSION, so for simplicity just
3495 scan all BLOCK_HEADER's and just skip *Model_Space and *Paper_Space. pspace might be NULL.
3496 #81 BLOCK_HEADER -
3497 LAYOUT - BLOCK - ENDBLK
3498 */
3499 for (i = 0; (BITCODE_BL)i < dwg->num_objects; i++)
3500 {
3501 const Dwg_Object *restrict obj = &dwg->object[i];
3502 if (obj->supertype == DWG_SUPERTYPE_OBJECT
3503 && obj->type == DWG_TYPE_BLOCK_HEADER)
3504 {
3505 error |= dxf_block_write (dat, obj, mspace, pspace, &i);
3506 }
3507 }
3508
3509 ENDSEC ();
3510 return error;
3511 }
3512
3513 static int
dxf_entities_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3514 dxf_entities_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3515 {
3516 int error = 0;
3517 Dwg_Object *restrict ms = dwg_model_space_object (dwg);
3518 Dwg_Object *restrict ps = dwg_paper_space_object (dwg);
3519 Dwg_Object *obj;
3520 if (!ms)
3521 return DWG_ERR_INVALIDDWG;
3522
3523 SECTION (ENTITIES);
3524 // how to order the entities:
3525 // 1. first all ms, then all ps
3526 #if 1
3527 // First mspace
3528 obj = get_first_owned_entity (ms); // first_entity or entities[0]
3529 while (obj)
3530 {
3531 int i = obj->index;
3532 error |= dwg_dxf_object (dat, obj, &i);
3533 obj = get_next_owned_block_entity (ms, obj); // until last_entity
3534 }
3535 // Then all pspace entities. just filter out other BLOCKS entities
3536 if (ps)
3537 {
3538 obj = get_first_owned_entity (ps);
3539 while (obj)
3540 {
3541 int i = obj->index;
3542 error |= dwg_dxf_object (dat, obj, &i);
3543 obj = get_next_owned_block_entity (ps, obj);
3544 }
3545 }
3546 #elif 0
3547 // 2. all entities in iteration order. filter out not owned by ms or ps entities.
3548 obj = get_first_owned_entity (ms);
3549 if (!obj)
3550 obj = get_first_owned_entity (ps);
3551 while (obj)
3552 {
3553 int i = obj->index;
3554 Dwg_Object_Ref *owner = obj->tio.entity->ownerhandle;
3555 if (!owner || (owner->obj == ms || owner->obj == ps))
3556 error |= dwg_dxf_object (dat, obj, &i);
3557 obj = dwg_next_entity (obj);
3558 }
3559 #else
3560 // 3. all objects in handle order, filter out not owned ms or ps entities.
3561 for (int i = 0; (BITCODE_BL)i < dwg->num_objects; i++)
3562 {
3563 Dwg_Object *obj = &dwg->object[i];
3564 if (obj->supertype == DWG_SUPERTYPE_ENTITY && obj->type != DWG_TYPE_BLOCK
3565 && obj->type != DWG_TYPE_ENDBLK)
3566 {
3567 Dwg_Object_Ref *owner = obj->tio.entity->ownerhandle;
3568 if (!owner || (owner->obj == ms || owner->obj == ps))
3569 error |= dwg_dxf_object (dat, obj, &i);
3570 }
3571 }
3572 #endif
3573 ENDSEC ();
3574 return error;
3575 }
3576
3577 // check for valid ownerhandle. set to 0 if not
3578 int
dxf_validate_DICTIONARY(Dwg_Object * obj)3579 dxf_validate_DICTIONARY (Dwg_Object *obj)
3580 {
3581 Dwg_Object_Ref *ownerhandle = obj->tio.object->ownerhandle;
3582 if (ownerhandle && !dwg_ref_object (obj->parent, ownerhandle))
3583 {
3584 LOG_INFO ("Wrong DICTIONARY.ownerhandle %lX\n", ownerhandle->absolute_ref);
3585 ownerhandle->absolute_ref = 0;
3586 return 0;
3587 }
3588 return 1;
3589 }
3590
3591 static int
dxf_objects_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3592 dxf_objects_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3593 {
3594 int error = 0;
3595 int i;
3596
3597 SECTION (OBJECTS);
3598 for (i = 0; (BITCODE_BL)i < dwg->num_objects; i++)
3599 {
3600 const Dwg_Object *restrict obj = &dwg->object[i];
3601 if (obj->supertype == DWG_SUPERTYPE_OBJECT
3602 && obj->type != DWG_TYPE_BLOCK_HEADER && !dwg_obj_is_control (obj))
3603 error |= dwg_dxf_object (dat, obj, &i);
3604 }
3605 ENDSEC ();
3606 return error;
3607 }
3608
3609 // New ACDSDATA r2013+ section, with ACDSSCHEMA elements
3610 static int
dxf_acds_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3611 dxf_acds_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3612 {
3613 //const char *section = "AcDsProtoype";
3614 Dwg_AcDs *_obj = &dwg->acds;
3615 if (0 && _obj->num_segidx)
3616 {
3617 SECTION (ACSDSDATA); // FIXME
3618 // 70
3619 // 71
3620 // 0 ACDSSCHEMA
3621 // TODO ...
3622 ENDSEC ();
3623 }
3624 return 0;
3625 }
3626
3627 GCC30_DIAG_IGNORE (-Wformat-nonliteral)
3628 // TODO: Beware, there's also a new ACDSDATA section, with ACDSSCHEMA elements
3629 // and the Thumbnail_Data (per block?)
3630 static int
dxf_thumbnail_write(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3631 dxf_thumbnail_write (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3632 {
3633 Bit_Chain *pic = (Bit_Chain *)&dwg->thumbnail;
3634 if (pic->chain && pic->size && pic->size > 10)
3635 {
3636 SECTION (THUMBNAILIMAGE);
3637 VALUE_RL (pic->size, 90);
3638 VALUE_BINARY (pic->chain, pic->size, 310);
3639 ENDSEC ();
3640 }
3641 return 0;
3642 }
3643
3644
3645 AFL_GCC_TOOBIG
3646 EXPORT int
dwg_write_dxf(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)3647 dwg_write_dxf (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
3648 {
3649 const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
3650 //struct Dwg_Header *obj = &dwg->header;
3651
3652 loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
3653 if (dat->from_version == R_INVALID)
3654 dat->from_version = dwg->header.from_version;
3655 if (dwg->header.version <= R_2000 && dwg->header.from_version > R_2000)
3656 dwg_fixup_BLOCKS_entities (dwg);
3657
3658 VALUE_TV (PACKAGE_STRING, 999);
3659
3660 // A minimal header requires only $ACADVER, $HANDSEED, and then ENTITIES
3661 // see https://pythonhosted.org/ezdxf/dxfinternals/filestructure.html
3662 dxf_header_write (dat, dwg);
3663
3664 if (!minimal)
3665 {
3666 // if downgraded to r13, but we still have classes, keep the
3667 // classes
3668 if ((dat->from_version >= R_13 && dwg->num_classes)
3669 || dat->version >= R_2000)
3670 {
3671 if (dxf_classes_write (dat, dwg) >= DWG_ERR_CRITICAL)
3672 goto fail;
3673 }
3674
3675 if (dxf_tables_write (dat, dwg) >= DWG_ERR_CRITICAL)
3676 goto fail;
3677
3678 if (dxf_blocks_write (dat, dwg) >= DWG_ERR_CRITICAL)
3679 goto fail;
3680 }
3681
3682 if (dxf_entities_write (dat, dwg) >= DWG_ERR_CRITICAL)
3683 goto fail;
3684
3685 if (!minimal)
3686 {
3687 SINCE (R_13)
3688 {
3689 if (dxf_objects_write (dat, dwg) >= DWG_ERR_CRITICAL)
3690 goto fail;
3691 }
3692 SINCE (R_2013)
3693 {
3694 if (dxf_acds_write (dat, dwg) >= DWG_ERR_CRITICAL)
3695 goto fail;
3696 }
3697 SINCE (R_2000)
3698 {
3699 if (dxf_thumbnail_write (dat, dwg) >= DWG_ERR_CRITICAL)
3700 goto fail;
3701 }
3702 }
3703 RECORD (EOF);
3704
3705 return 0;
3706 fail:
3707 return 1;
3708 }
3709 AFL_GCC_POP
3710
3711 #undef IS_PRINT
3712 #undef IS_DXF
3713