1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2009-2010,2018-2021 Free Software Foundation, Inc. */
5 /* Copyright (C) 2010 Thien-Thi Nguyen */
6 /* */
7 /* This library is free software, licensed under the terms of the GNU */
8 /* General Public License as published by the Free Software Foundation, */
9 /* either version 3 of the License, or (at your option) any later version. */
10 /* You should have received a copy of the GNU General Public License */
11 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
12 /*****************************************************************************/
13
14 /*
15 * encode.c: encoding functions to write a DWG
16 * written by Felipe Castro
17 * modified by Felipe Corrêa da Silva Sances
18 * modified by Rodrigo Rodrigues da Silva
19 * modified by Thien-Thi Nguyen
20 * modified by Till Heuschmann
21 * modified by Anderson Pierre Cardoso
22 * modified by Reini Urban
23 */
24
25 //#define HAVE_COMPRESS_R2004_SECTION
26
27 #include "config.h"
28 #ifdef __STDC_ALLOC_LIB__
29 # define __STDC_WANT_LIB_EXT2__ 1 /* for strdup */
30 #else
31 # define _USE_BSD 1
32 #endif
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdint.h>
37 #include <string.h>
38 #include <assert.h>
39 #ifdef HAVE_CTYPE_H
40 # include <ctype.h>
41 #endif
42
43 #include "common.h"
44 #include "bits.h"
45 #include "dwg.h"
46 #include "encode.h"
47 #include "decode.h"
48 #include "classes.h"
49 #include "free.h"
50
51 // from dynapi
52 bool is_dwg_object (const char *name);
53 bool is_dwg_entity (const char *name);
54 int dwg_dynapi_entity_size (const char *restrict name);
55 // from dwg_api
56 BITCODE_T dwg_add_u8_input (Dwg_Data *restrict dwg,
57 const char *restrict u8str);
58 Dwg_Object_APPID *dwg_add_APPID (Dwg_Data *restrict dwg,
59 const char *restrict name);
60 unsigned long dwg_obj_generic_handlevalue (void *_obj);
61
62 /* The logging level for the write (encode) path. */
63 static unsigned int loglevel;
64 /* the current version per spec block */
65 static unsigned int cur_ver = 0;
66 static BITCODE_BL rcount1 = 0, rcount2 = 0;
67
68 #ifdef USE_TRACING
69 /* This flag means we have checked the environment variable
70 LIBREDWG_TRACE and set `loglevel' appropriately. */
71 static bool env_var_checked_p;
72 #endif /* USE_TRACING */
73 #define DWG_LOGLEVEL loglevel
74
75 #include "logging.h"
76
77 /*--------------------------------------------------------------------------------
78 * spec MACROS
79 */
80
81 #define ACTION encode
82 #define IS_ENCODER
83
84 #define ANYCODE -1
85
86 #undef LOG_POS
87 #define LOG_POS \
88 LOG_INSANE (" @%lu.%u", obj ? dat->byte - obj->address : dat->byte, dat->bit)\
89 LOG_TRACE ("\n")
90 #define LOG_RPOS \
91 LOG_INSANE (" @%lu.%u", dat->byte, dat->bit) \
92 LOG_TRACE ("\n")
93 #define LOG_HPOS \
94 LOG_INSANE (" @%lu.%u", \
95 obj && hdl_dat->byte > obj->address \
96 ? hdl_dat->byte - obj->address \
97 : hdl_dat->byte, \
98 hdl_dat->bit) \
99 LOG_TRACE ("\n")
100
101 #define VALUE(value, type, dxf) \
102 { \
103 bit_write_##type (dat, value); \
104 LOG_TRACE (FORMAT_##type " [" #type " %d]", (BITCODE_##type)value, dxf); \
105 LOG_POS \
106 }
107 #define VALUE_RC(value, dxf) VALUE (value, RC, dxf)
108 #define VALUE_RS(value, dxf) VALUE (value, RS, dxf)
109 #define VALUE_RL(value, dxf) VALUE (value, RL, dxf)
110 #define VALUE_BS(value, dxf) VALUE (value, BS, dxf)
111 #define VALUE_BL(value, dxf) VALUE (value, BL, dxf)
112 #define VALUE_RD(value, dxf) VALUE (value, RD, dxf)
113 #define VALUE_BD(value, dxf) VALUE (value, BD, dxf)
114
115 #define FIELD(nam, type) \
116 { \
117 bit_write_##type (dat, _obj->nam); \
118 FIELD_TRACE (nam, type); \
119 }
120 #define FIELDG(nam, type, dxf) \
121 { \
122 bit_write_##type (dat, _obj->nam); \
123 FIELD_G_TRACE (nam, type, dxf); \
124 }
125 #define FIELD_TRACE(nam, type) \
126 LOG_TRACE (#nam ": " FORMAT_##type, _obj->nam) \
127 LOG_POS
128 #define FIELD_G_TRACE(nam, type, dxfgroup) \
129 LOG_TRACE (#nam ": " FORMAT_##type " [" #type " " #dxfgroup "]", _obj->nam) \
130 LOG_POS
131 #define FIELD_CAST(nam, type, cast, dxf) \
132 { \
133 bit_write_##type (dat, (BITCODE_##type)_obj->nam); \
134 LOG_TRACE (#nam ": " FORMAT_##type " [" #type " " #dxf "]", \
135 (BITCODE_##type)_obj->nam); \
136 LOG_POS \
137 }
138 #define SUB_FIELD(o, nam, type, dxf) FIELD (o.nam, type)
139 #define SUB_FIELD_CAST(o, nam, type, cast, dxf) \
140 { \
141 bit_write_##type (dat, (BITCODE_##type)_obj->o.nam); \
142 FIELD_G_TRACE (o.nam, cast, dxf); \
143 }
144
145 #define FIELD_VALUE(nam) _obj->nam
146
147 #define FIELD_B(nam, dxf) FIELDG (nam, B, dxf)
148 #define FIELD_BB(nam, dxf) FIELDG (nam, BB, dxf)
149 #define FIELD_3B(nam, dxf) FIELDG (nam, 3B, dxf)
150 #define FIELD_BS(nam, dxf) FIELDG (nam, BS, dxf)
151 #define FIELD_BSd(nam, dxf) FIELD_CAST (nam, BS, BSd, dxf)
152 #define FIELD_RSx(nam, dxf) FIELD_CAST (nam, RS, RSx, dxf)
153 #define FIELD_RLx(nam, dxf) FIELD_CAST (nam, RL, RLx, dxf)
154 #define FIELD_BLx(nam, dxf) FIELD_CAST (nam, BL, BLx, dxf)
155 #define FIELD_BLd(nam, dxf) FIELD_CAST (nam, BL, BLd, dxf)
156 #define FIELD_RLd(nam, dxf) FIELD_CAST (nam, RL, RLd, dxf)
157 #define FIELD_BL(nam, dxf) FIELDG (nam, BL, dxf)
158 #define FIELD_BLL(nam, dxf) FIELDG (nam, BLL, dxf)
159 #define FIELD_BD(nam, dxf) FIELDG (nam, BD, dxf)
160 #define FIELD_RC(nam, dxf) FIELDG (nam, RC, dxf)
161 #define FIELD_RS(nam, dxf) FIELDG (nam, RS, dxf)
162 #define FIELD_RD(nam, dxf) FIELDG (nam, RD, dxf)
163 #define FIELD_RL(nam, dxf) FIELDG (nam, RL, dxf)
164 #define FIELD_RLL(nam, dxf) FIELDG (nam, RLL, dxf)
165 #define FIELD_RLLu(nam, dxf) \
166 { \
167 bit_write_RLL (dat, _obj->nam); \
168 FIELD_G_TRACE (nam, BLL, dxf); \
169 }
170 #define FIELD_MC(nam, dxf) FIELDG (nam, MC, dxf)
171 #define FIELD_MS(nam, dxf) FIELDG (nam, MS, dxf)
172 #define FIELD_TV(nam, dxf) \
173 { \
174 IF_ENCODE_FROM_EARLIER \
175 { \
176 if (!_obj->nam) \
177 _obj->nam = strdup (""); \
178 } \
179 bit_write_TV (dat, _obj->nam); \
180 LOG_TRACE (#nam ": \"%s\" [TV %d]", _obj->nam, dxf); \
181 LOG_POS \
182 }
183 // may need to convert from/to TV<=>TU
184 #define FIELD_T(nam, dxf) \
185 { \
186 if (dat->version < R_2007) \
187 { \
188 bit_write_T (dat, _obj->nam); \
189 LOG_TRACE (#nam ": \"%s\" [T %d]", _obj->nam, dxf); \
190 LOG_POS \
191 } \
192 else \
193 { \
194 bit_write_T (str_dat, _obj->nam); \
195 LOG_TRACE_TU (#nam, _obj->nam, dxf); \
196 } \
197 }
198 #define FIELD_TF(nam, len, dxf) \
199 { \
200 LOG_TRACE (#nam ": [TF %d %d]\n", (int)len, dxf); \
201 if (len > 0) \
202 { \
203 if (!_obj->nam) \
204 { /* empty field, write zeros */ \
205 for (int _i = 0; _i < (int)(len); _i++) \
206 bit_write_RC (dat, 0); \
207 } \
208 else \
209 { \
210 bit_write_TF (dat, (BITCODE_TF)_obj->nam, len); \
211 } \
212 } \
213 LOG_TRACE_TF (FIELD_VALUE (nam), (int)len); \
214 }
215 #define FIELD_TFF(nam, len, dxf) FIELD_TF (nam, len, dxf)
216 #define FIELD_TU(nam, dxf) \
217 { \
218 if (_obj->nam) \
219 bit_write_TU (str_dat, (BITCODE_TU)_obj->nam); \
220 LOG_TRACE_TU (#nam, (BITCODE_TU)_obj->nam, dxf); \
221 }
222 #define FIELD_TU16(nam, dxf) \
223 { \
224 if (_obj->nam) \
225 bit_write_TU16 (str_dat, _obj->nam); \
226 LOG_TRACE_TU (#nam, (BITCODE_TU)_obj->nam, dxf); \
227 }
228 #define FIELD_T32(nam, dxf) \
229 { \
230 if (_obj->nam) \
231 bit_write_T32 (str_dat, _obj->nam); \
232 if (dat->version < R_2007) \
233 LOG_TRACE (#nam ": \"%s\" [T32 %d]\n", _obj->nam, dxf) \
234 else \
235 LOG_TRACE_TU (#nam, (BITCODE_TU)_obj->nam, dxf) \
236 }
237 #define FIELD_TU32(nam, dxf) \
238 { \
239 if (_obj->nam) \
240 bit_write_TU32 (str_dat, _obj->nam); \
241 if (dat->version < R_2007) \
242 LOG_TRACE (#nam ": \"%s\" [TU32 %d]\n", _obj->nam, dxf) \
243 else \
244 LOG_TRACE_TU (#nam, (BITCODE_TU)_obj->nam, dxf) \
245 }
246 #define FIELD_BT(nam, dxf) FIELDG (nam, BT, dxf);
247
248 #define _FIELD_DD(nam, _default, dxf) \
249 bit_write_DD (dat, FIELD_VALUE (nam), _default);
250 #define FIELD_DD(nam, _default, dxf) \
251 { \
252 BITCODE_BB b1 = _FIELD_DD (nam, _default, dxf); \
253 if (b1 == 3) \
254 LOG_TRACE (#nam ": %f [DD %d]", _obj->nam, dxf) \
255 else \
256 LOG_TRACE (#nam ": %f [DD/%d %d]", _obj->nam, b1, dxf) \
257 LOG_POS \
258 }
259 #define FIELD_2DD(nam, def, dxf) \
260 { \
261 BITCODE_BB b2, b1 = _FIELD_DD (nam.x, FIELD_VALUE (def.x), dxf); \
262 b2 = _FIELD_DD (nam.y, FIELD_VALUE (def.y), dxf + 10); \
263 if (b1 == 3 && b2 == 3) \
264 LOG_TRACE (#nam ": (%f, %f) [2DD %d]", _obj->nam.x, _obj->nam.y, dxf) \
265 else \
266 LOG_TRACE (#nam ": (%f, %f) [2DD/%d%d %d]", _obj->nam.x, _obj->nam.y, \
267 b1, b2, dxf) \
268 LOG_POS \
269 }
270 #define FIELD_3DD(nam, def, dxf) \
271 { \
272 _FIELD_DD (nam.x, FIELD_VALUE (def.x), dxf); \
273 _FIELD_DD (nam.y, FIELD_VALUE (def.y), dxf + 10); \
274 _FIELD_DD (nam.z, FIELD_VALUE (def.z), dxf + 20); \
275 LOG_TRACE (#nam ": (%f, %f, %f) [3DD %d]", _obj->nam.x, _obj->nam.y, \
276 _obj->nam.z, dxf) \
277 LOG_POS \
278 }
279 #define FIELD_2RD(nam, dxf) \
280 { \
281 bit_write_RD (dat, _obj->nam.x); \
282 bit_write_RD (dat, _obj->nam.y); \
283 LOG_TRACE (#nam ": (%f, %f) [3RD %d]", _obj->nam.x, _obj->nam.y, dxf) \
284 LOG_POS \
285 }
286 #define FIELD_2BD(nam, dxf) \
287 { \
288 bit_write_BD (dat, _obj->nam.x); \
289 bit_write_BD (dat, _obj->nam.y); \
290 LOG_TRACE (#nam ": (%f, %f) [3BD %d]", _obj->nam.x, _obj->nam.y, dxf) \
291 LOG_POS \
292 }
293 #define FIELD_2BD_1(nam, dxf) FIELD_2BD (nam, dxf)
294 #define FIELD_3RD(nam, dxf) \
295 { \
296 bit_write_RD (dat, _obj->nam.x); \
297 bit_write_RD (dat, _obj->nam.y); \
298 bit_write_RD (dat, _obj->nam.z); \
299 LOG_TRACE (#nam ": (%f, %f, %f) [3RD %d]", _obj->nam.x, _obj->nam.y, \
300 _obj->nam.z, dxf) \
301 LOG_POS \
302 }
303 #define FIELD_3BD(nam, dxf) \
304 { \
305 bit_write_BD (dat, _obj->nam.x); \
306 bit_write_BD (dat, _obj->nam.y); \
307 bit_write_BD (dat, _obj->nam.z); \
308 LOG_TRACE (#nam ": (%f, %f, %f) [3BD %d]", _obj->nam.x, _obj->nam.y, \
309 _obj->nam.z, dxf) \
310 LOG_POS \
311 }
312 #define FIELD_3BD_1(nam, dxf) FIELD_3BD (nam, dxf)
313 #define FIELD_3DPOINT(nam, dxf) FIELD_3BD (nam, dxf)
314 #define FIELD_4BITS(nam, dxf) \
315 { \
316 unsigned char _b = (unsigned char)_obj->nam; \
317 bit_write_4BITS (dat, _b); \
318 LOG_TRACE (#nam ": b%d%d%d%d [4BITS %d]", _b & 8, _b & 4, _b & 2, \
319 _b & 1, dxf); \
320 LOG_POS \
321 }
322 #define FIELD_TIMEBLL(nam, dxf) \
323 { \
324 bit_write_TIMEBLL (dat, (BITCODE_TIMEBLL)_obj->nam); \
325 LOG_TRACE (#nam ": " FORMAT_BL "." FORMAT_BL " [TIMEBLL %d]", \
326 _obj->nam.days, _obj->nam.ms, dxf); \
327 LOG_POS \
328 }
329 #define FIELD_TIMERLL(nam, dxf) \
330 { \
331 bit_write_TIMERLL (dat, (BITCODE_TIMERLL)_obj->nam); \
332 LOG_TRACE (#nam ": " FORMAT_RL "." FORMAT_RL " [TIMERLL %d]", \
333 _obj->nam.days, _obj->nam.ms, dxf); \
334 LOG_POS \
335 }
336
337 #define FIELD_CMC(color, dxf) \
338 { \
339 bit_write_CMC (dat, str_dat, &_obj->color); \
340 LOG_TRACE (#color ".index: %d [CMC.BS %d]\n", _obj->color.index, dxf); \
341 LOG_INSANE (" @%lu.%u\n", obj ? dat->byte - obj->address : dat->byte, dat->bit) \
342 if (dat->version >= R_2004) \
343 { \
344 LOG_TRACE (#color ".rgb: 0x%08x [CMC.BL %d]\n", \
345 (unsigned)_obj->color.rgb, dxf + 420 - 62); \
346 LOG_TRACE (#color ".flag: 0x%x [CMC.RC]\n", \
347 (unsigned)_obj->color.flag); \
348 if (_obj->color.flag & 1) \
349 LOG_TRACE (#color ".name: %s [CMC.T]\n", _obj->color.name); \
350 if (_obj->color.flag & 2) \
351 LOG_TRACE (#color ".bookname: %s [CMC.T]\n", \
352 _obj->color.book_name); \
353 LOG_INSANE (" @%lu.%u\n", obj ? dat->byte - obj->address : dat->byte, dat->bit) \
354 } \
355 }
356 #define SUB_FIELD_CMC(o, color, dxf) \
357 { \
358 bit_write_CMC (dat, str_dat, &_obj->o.color); \
359 LOG_TRACE (#color ".index: %d [CMC.BS %d]\n", _obj->o.color.index, dxf); \
360 LOG_INSANE (" @%lu.%u\n", obj ? dat->byte - obj->address : dat->byte, \
361 dat->bit) \
362 if (dat->version >= R_2004) \
363 { \
364 LOG_TRACE (#color ".rgb: 0x%06x [CMC.BL %d]\n", \
365 (unsigned)_obj->o.color.rgb, dxf + 420 - 62); \
366 LOG_TRACE (#color ".flag: 0x%x [CMC.RC]\n", \
367 (unsigned)_obj->o.color.flag); \
368 if (_obj->o.color.flag & 1) \
369 LOG_TRACE (#color ".name: %s [CMC.T]\n", _obj->o.color.name); \
370 if (_obj->o.color.flag & 2) \
371 LOG_TRACE (#color ".bookname: %s [CMC.T]\n", \
372 _obj->o.color.book_name); \
373 LOG_INSANE (" @%lu.%u\n", obj ? dat->byte - obj->address : dat->byte, \
374 dat->bit) \
375 } \
376 }
377
378 #define LOG_TF(level, var, len) \
379 if (var) \
380 { \
381 int _i; \
382 for (_i = 0; _i < (len); _i++) \
383 { \
384 LOG (level, "%02X", (unsigned char)((char *)var)[_i]); \
385 } \
386 LOG (level, "\n"); \
387 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_INSANE) \
388 { \
389 for (_i = 0; _i < (len); _i++) \
390 { \
391 unsigned char c = ((unsigned char *)var)[_i]; \
392 LOG_INSANE ("%-2c", isprint (c) ? c : ' '); \
393 } \
394 LOG_INSANE ("\n"); \
395 } \
396 }
397 #define LOG_TRACE_TF(var, len) LOG_TF (TRACE, var, len)
398 #define LOG_INSANE_TF(var, len) LOG_TF (INSANE, var, len)
399
400 #define FIELD_BE(nam, dxf) \
401 bit_write_BE (dat, FIELD_VALUE (nam.x), FIELD_VALUE (nam.y), \
402 FIELD_VALUE (nam.z));
403
404 #define OVERFLOW_CHECK(nam, size) \
405 if ((long)(size) > 0xff00L || (!_obj->nam && size) || (_obj->nam && !size)) \
406 { \
407 LOG_ERROR ("Invalid " #nam " %ld", (long)size); \
408 return DWG_ERR_VALUEOUTOFBOUNDS; \
409 }
410 #define OVERFLOW_CHECK_LV(nam, size) \
411 if ((long)(size) > 0xff00L) \
412 { \
413 LOG_ERROR ("Invalid " #nam " %ld, set to 0", (long)size); \
414 size = 0; \
415 return DWG_ERR_VALUEOUTOFBOUNDS; \
416 }
417 #define OVERFLOW_NULL_CHECK_LV(nam, size) \
418 if ((long)(size) > 0xff00L || (!_obj->nam && size) || (_obj->nam && !size)) \
419 { \
420 LOG_ERROR ("Invalid " #nam " %ld, set to 0", (long)size); \
421 size = 0; \
422 return DWG_ERR_VALUEOUTOFBOUNDS; \
423 }
424
425 #define FIELD_2RD_VECTOR(nam, size, dxf) \
426 OVERFLOW_NULL_CHECK_LV (nam, _obj->size) \
427 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
428 { \
429 FIELD_2RD (nam[vcount], dxf); \
430 }
431
432 #define FIELD_2DD_VECTOR(nam, size, dxf) \
433 OVERFLOW_NULL_CHECK_LV (nam, _obj->size) \
434 if (_obj->size) \
435 FIELD_2RD (nam[0], dxf); \
436 for (vcount = 1; vcount < (BITCODE_BL)_obj->size; vcount++) \
437 { \
438 FIELD_2DD (nam[vcount], nam[vcount - 1], dxf); \
439 }
440
441 #define FIELD_3DPOINT_VECTOR(nam, size, dxf) \
442 OVERFLOW_NULL_CHECK_LV (nam, _obj->size) \
443 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
444 { \
445 FIELD_3DPOINT (nam[vcount], dxf); \
446 }
447
448 #define REACTORS(code) \
449 if (obj->tio.object->reactors) \
450 { \
451 OVERFLOW_CHECK_LV (num_reactors, obj->tio.object->num_reactors) \
452 SINCE (R_13) \
453 { \
454 for (vcount = 0; vcount < (BITCODE_BL)obj->tio.object->num_reactors; \
455 vcount++) \
456 { \
457 VALUE_HANDLE (obj->tio.object->reactors[vcount], reactors, code, \
458 330); \
459 } \
460 } \
461 }
462
463 #define XDICOBJHANDLE(code) \
464 RESET_VER \
465 SINCE (R_2004) \
466 { \
467 if (!obj->tio.object->is_xdic_missing) \
468 { \
469 VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, \
470 360); \
471 } \
472 } \
473 else \
474 { \
475 SINCE (R_13) \
476 { \
477 VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, \
478 360); \
479 } \
480 } \
481 RESET_VER
482
483 #define ENT_XDICOBJHANDLE(code) \
484 RESET_VER \
485 SINCE (R_2004) \
486 { \
487 if (!obj->tio.entity->is_xdic_missing) \
488 { \
489 VALUE_HANDLE (obj->tio.entity->xdicobjhandle, xdicobjhandle, 3, \
490 360); \
491 } \
492 } \
493 else \
494 { \
495 SINCE (R_13) \
496 { \
497 VALUE_HANDLE (obj->tio.entity->xdicobjhandle, xdicobjhandle, 3, \
498 360); \
499 } \
500 } \
501 RESET_VER
502
503 // FIELD_VECTOR_N(nam, type, size, dxf):
504 // writes a 'size' elements vector of data of the type indicated by 'type'
505 #define FIELD_VECTOR_N(nam, type, size, dxf) \
506 if (size > 0 && _obj->nam) \
507 { \
508 OVERFLOW_CHECK (nam, size) \
509 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
510 { \
511 bit_write_##type (dat, _obj->nam[vcount]); \
512 LOG_TRACE (#nam "[%ld]: " FORMAT_##type " [%s %d]", (long)vcount, \
513 _obj->nam[vcount], #type, dxf) \
514 LOG_POS \
515 } \
516 }
517 #define FIELD_VECTOR_T(nam, type, size, dxf) \
518 if (_obj->size > 0 && _obj->nam) \
519 { \
520 OVERFLOW_CHECK_LV (nam, _obj->size) \
521 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
522 { \
523 if (dat->version != dat->from_version) \
524 FIELD_##type (nam[vcount], dxf) else if (dat->version < R_2007) \
525 { \
526 bit_write_TV (dat, (BITCODE_TV)_obj->nam[vcount]); \
527 LOG_TRACE (#nam "[%d]: \"%s\" [TV %d]", (int)vcount, \
528 _obj->nam[vcount], dxf) \
529 LOG_POS \
530 } \
531 else \
532 { \
533 bit_write_##type (dat, _obj->nam[vcount]); \
534 LOG_TRACE_TU (#nam, _obj->nam[vcount], dxf) \
535 } \
536 } \
537 RESET_VER \
538 }
539 #define FIELD_VECTOR_T1(nam, type, size, dxf) \
540 if (_obj->size > 0 && _obj->nam) \
541 { \
542 OVERFLOW_CHECK_LV (nam, _obj->size) \
543 for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++) \
544 { \
545 if (dat->version < R_2007) \
546 { \
547 unsigned _len = strlen (_obj->nam[vcount]); \
548 bit_write_BS (dat, _len); \
549 bit_write_TF (dat, (BITCODE_TF)_obj->nam[vcount], _len); \
550 LOG_TRACE (#nam "[%d]: \"%s\" [TV1 %d]", (int)vcount, \
551 _obj->nam[vcount], dxf) \
552 LOG_POS \
553 } \
554 else \
555 { \
556 bit_write_##type (dat, _obj->nam[vcount]); \
557 LOG_TRACE_TU (#nam, _obj->nam[vcount], dxf) \
558 } \
559 } \
560 RESET_VER \
561 }
562
563 #define FIELD_VECTOR(nam, type, size, dxf) \
564 FIELD_VECTOR_N (nam, type, _obj->size, dxf)
565 #define FIELD_VECTOR_INL(nam, type, size, dxf) \
566 FIELD_VECTOR_N (nam, type, size, dxf)
567
568 #define SUB_FIELD_VECTOR_TYPESIZE(o, nam, size, typesize, dxf) \
569 if (_obj->o.size > 0 && _obj->o.nam) \
570 { \
571 OVERFLOW_CHECK (nam, _obj->o.size) \
572 for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++) \
573 { \
574 bit_write_##type (dat, _obj->nam[vcount]); \
575 switch (typesize) \
576 { \
577 case 0: \
578 break; \
579 case 1: \
580 bit_write_RC (dat, _obj->o.name[vcount]); \
581 break; \
582 case 2: \
583 bit_write_RS (dat, _obj->o.name[vcount]); \
584 break; \
585 case 4: \
586 bit_write_RL (dat, _obj->o.name[vcount]); \
587 break; \
588 case 8: \
589 bit_write_RLL (dat, _obj->o.name[vcount]); \
590 break; \
591 default: \
592 LOG_ERROR ("Unkown SUB_FIELD_VECTOR_TYPE " #nam " typesize %d", \
593 typesize); \
594 break; \
595 } \
596 LOG_TRACE (#nam "[%u]: %d\n", vcount, _obj->nam[vcount]) \
597 } \
598 }
599
600 #define VALUE_HANDLE(hdlptr, nam, handle_code, dxf) \
601 IF_ENCODE_SINCE_R13 \
602 { \
603 RESET_VER \
604 if (!hdlptr) \
605 { \
606 Dwg_Handle null_handle = { 0, 0, 0UL, 0 }; \
607 null_handle.code = handle_code; \
608 bit_write_H (hdl_dat, &null_handle); \
609 LOG_TRACE (#nam ": (%d.0.0) abs:0 [H %d]", handle_code, dxf) \
610 LOG_HPOS \
611 } \
612 else \
613 { \
614 if (handle_code != ANYCODE && (hdlptr)->handleref.code != handle_code \
615 && (handle_code == 4 && (hdlptr)->handleref.code < 6)) \
616 { \
617 LOG_WARN ("Expected a CODE %d handle, got a %d", handle_code, \
618 (hdlptr)->handleref.code); \
619 } \
620 bit_write_H (hdl_dat, &(hdlptr)->handleref); \
621 LOG_TRACE (#nam ": " FORMAT_REF " [H %d]", ARGS_REF (hdlptr), dxf) \
622 LOG_HPOS \
623 } \
624 }
625
626 #define FIELD_HANDLE(nam, handle_code, dxf) \
627 VALUE_HANDLE (_obj->nam, nam, handle_code, dxf)
628 #define SUB_FIELD_HANDLE(o, nam, handle_code, dxf) \
629 VALUE_HANDLE (_obj->o.nam, nam, handle_code, dxf)
630 #define FIELD_DATAHANDLE(nam, handle_code, dxf) \
631 { \
632 bit_write_H (dat, _obj->nam ? &_obj->nam->handleref : NULL); \
633 }
634
635 #define FIELD_HANDLE_N(nam, vcount, handle_code, dxf) \
636 IF_ENCODE_SINCE_R13 \
637 { \
638 RESET_VER \
639 if (!_obj->nam) \
640 { \
641 bit_write_H (hdl_dat, NULL); \
642 LOG_TRACE (#nam "[%d]: NULL %d [H* %d]", (int)vcount, handle_code, \
643 dxf) \
644 LOG_HPOS \
645 } \
646 else \
647 { \
648 if (handle_code != ANYCODE \
649 && _obj->nam->handleref.code != handle_code \
650 && (handle_code == 4 && _obj->nam->handleref.code < 6)) \
651 { \
652 LOG_WARN ("Expected a CODE %x handle, got a %x", handle_code, \
653 _obj->nam->handleref.code); \
654 } \
655 bit_write_H (hdl_dat, &_obj->nam->handleref); \
656 LOG_TRACE (#nam "[%d]: " FORMAT_REF " [H* %d]", (int)vcount, \
657 ARGS_REF (_obj->nam), dxf) \
658 LOG_HPOS \
659 } \
660 }
661
662 #define HANDLE_VECTOR_N(nam, size, code, dxf) \
663 if (size > 0 && _obj->nam) \
664 { \
665 OVERFLOW_CHECK (nam, size) \
666 for (vcount = 0; vcount < (BITCODE_BL)size; vcount++) \
667 { \
668 if (_obj->nam[vcount]) \
669 { \
670 FIELD_HANDLE_N (nam[vcount], vcount, code, dxf); \
671 } \
672 } \
673 }
674
675 #define FIELD_NUM_INSERTS(num_inserts, type, dxf) \
676 for (vcount = 0; vcount < FIELD_VALUE (num_inserts); vcount++) \
677 { \
678 bit_write_RC (dat, 1); \
679 } \
680 bit_write_RC (dat, 0); \
681 LOG_TRACE ("num_inserts: %d [RC* 0]", FIELD_VALUE (num_inserts)) \
682 LOG_POS
683
684 #define HANDLE_VECTOR(nam, sizefield, code, dxf) \
685 HANDLE_VECTOR_N (nam, FIELD_VALUE (sizefield), code, dxf)
686
687 #define FIELD_XDATA(nam, size) \
688 error |= dwg_encode_xdata (dat, _obj, _obj->size)
689
690 #define COMMON_ENTITY_HANDLE_DATA \
691 SINCE (R_13) \
692 { \
693 START_HANDLE_STREAM; \
694 } \
695 RESET_VER
696
697 #define START_OBJECT_HANDLE_STREAM START_HANDLE_STREAM
698 #define CONTROL_HANDLE_STREAM START_HANDLE_STREAM
699
700 #define SECTION_STRING_STREAM \
701 { \
702 Bit_Chain sav_dat = *dat; \
703 dat = str_dat;
704
705 /* TODO: dump all TU strings here */
706 #define START_STRING_STREAM \
707 bit_write_B (dat, obj->has_strings); \
708 RESET_VER \
709 if (obj->has_strings) \
710 { \
711 Bit_Chain sav_dat = *dat; \
712 obj_string_stream (dat, obj, dat);
713
714 #define END_STRING_STREAM \
715 *dat = sav_dat; \
716 }
717 #define ENCODE_COMMON_HANDLES \
718 if (obj->supertype == DWG_SUPERTYPE_OBJECT && dat->version >= R_13) \
719 { \
720 VALUE_HANDLE (obj->tio.object->ownerhandle, ownerhandle, 4, 330); \
721 REACTORS (4); \
722 XDICOBJHANDLE (3); \
723 } \
724 else if (obj->supertype == DWG_SUPERTYPE_ENTITY && dat->version >= R_13) \
725 { \
726 error |= dwg_encode_common_entity_handle_data (dat, hdl_dat, obj); \
727 }
728
729 #define START_HANDLE_STREAM \
730 LOG_INSANE ("HANDLE_STREAM @%lu.%u\n", dat->byte - obj->address, dat->bit) \
731 if (!obj->bitsize || \
732 /* DD sizes can vary, but let unknown_bits asis */ \
733 has_entity_DD (obj) || \
734 /* strings may be zero-terminated or not */ \
735 obj_has_strings (obj) || \
736 (dwg->header.version != dwg->header.from_version \
737 && obj->fixedtype != DWG_TYPE_UNKNOWN_OBJ \
738 && obj->fixedtype != DWG_TYPE_UNKNOWN_ENT)) \
739 { \
740 obj->bitsize = bit_position (dat) - (obj->address * 8); \
741 LOG_TRACE ("-bitsize calc from HANDLE_STREAM " FORMAT_RL " @%lu.%u (%lu)\n", \
742 obj->bitsize, dat->byte - obj->address, dat->bit, obj->address); \
743 obj->was_bitsize_set = 1; \
744 } \
745 if (!obj->hdlpos) \
746 obj->hdlpos = bit_position (dat); \
747 { \
748 unsigned long _hpos = bit_position (hdl_dat); \
749 if (_hpos > 0) \
750 { \
751 /* save away special accumulated hdls, need to write common first */ \
752 Bit_Chain dat1 = *hdl_dat; \
753 Bit_Chain dat2; \
754 bit_chain_init_dat (&dat2, 12, dat); \
755 hdl_dat = &dat2; \
756 ENCODE_COMMON_HANDLES \
757 obj_flush_hdlstream (obj, dat, hdl_dat); /* common */ \
758 obj_flush_hdlstream (obj, dat, &dat1); /* special accumulated */ \
759 bit_chain_free (&dat1); \
760 bit_chain_free (&dat2); \
761 *hdl_dat = *dat; \
762 hdl_dat = dat; \
763 } \
764 else \
765 { \
766 if (hdl_dat != dat) \
767 bit_chain_free (hdl_dat); \
768 hdl_dat = dat; \
769 ENCODE_COMMON_HANDLES \
770 } \
771 } \
772 RESET_VER
773
774 static void
obj_flush_hdlstream(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Bit_Chain * restrict hdl_dat)775 obj_flush_hdlstream (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
776 Bit_Chain *restrict hdl_dat)
777 {
778 unsigned long datpos = bit_position (dat);
779 unsigned long hdlpos = bit_position (hdl_dat);
780 unsigned long objpos = obj->address * 8;
781 LOG_TRACE ("Flush handle stream of size %lu (@%lu.%u) to @%lu.%lu\n", hdlpos,
782 hdl_dat->byte, hdl_dat->bit, (datpos - objpos) / 8,
783 (datpos - objpos) % 8);
784 bit_copy_chain (dat, hdl_dat);
785 }
786
787 #if 0
788 /** See dec_macro.h instead.
789 Returns -1 if not added, else returns the new objid.
790 Does a complete handleref rescan to invalidate and resolve
791 all internal obj pointers after a object[] realloc.
792 */
793 EXPORT long dwg_add_##token (Dwg_Data * dwg) \
794 { \
795 Bit_Chain dat = { 0 }; \
796 BITCODE_BL num_objs = dwg->num_objects; \
797 int error = 0; \
798 dat.size = sizeof(Dwg_Entity_##token) + 40; \
799 LOG_INFO ("Add entity " #token " ") \
800 dat.chain = calloc (dat.size, 1); \
801 dat.version = dwg->header.version; \
802 dat.from_version = dwg->header.from_version; \
803 bit_write_MS (&dat, dat.size); \
804 if (dat.version >= R_2010) { \
805 /* FIXME: should be UMC handlestream_size */\
806 bit_write_UMC (&dat, 8*sizeof(Dwg_Entity_##token)); \
807 bit_write_BOT &dat, DWG_TYPE_##token); \
808 } else { \
809 bit_write_BS (&dat, DWG_TYPE_##token); \
810 } \
811 bit_set_position (&dat, 0); \
812 error = dwg_decode_add_object (dwg, &dat, &dat, 0);\
813 if (-1 == error) \
814 dwg_resolve_objectrefs_silent (dwg); \
815 if (num_objs == dwg->num_objects) \
816 return -1; \
817 else \
818 return (long)dwg->num_objects; \
819 }
820
821 EXPORT long dwg_add_##token (Dwg_Data * dwg) \
822 { \
823 Bit_Chain dat = { 0 }; \
824 int error = 0; \
825 BITCODE_BL num_objs = dwg->num_objects; \
826 dat.size = sizeof(Dwg_Object_##token) + 40; \
827 LOG_INFO ("Add object " #token " ") \
828 dat.chain = calloc (dat.size, 1); \
829 dat.version = dwg->header.version; \
830 dat.from_version = dwg->header.from_version; \
831 bit_write_MS (&dat, dat.size); \
832 if (dat.version >= R_2010) { \
833 /* FIXME: should be UMC handlestream_size */ \
834 bit_write_UMC (&dat, 8*sizeof(Dwg_Object_##token)); \
835 bit_write_BOT (&dat, DWG_TYPE_##token); \
836 } else { \
837 bit_write_BS (&dat, DWG_TYPE_##token); \
838 } \
839 bit_set_position(&dat, 0); \
840 error = dwg_decode_add_object(dwg, &dat, &dat, 0);\
841 if (-1 == error) \
842 dwg_resolve_objectrefs_silent(dwg); \
843 if (num_objs == dwg->num_objects) \
844 return -1; \
845 else \
846 return (long)dwg->num_objects; \
847 }
848
849 #endif
850
851 #define DWG_ENTITY(token) \
852 static int dwg_encode_##token##_private ( \
853 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
854 Dwg_Object *restrict obj); \
855 static int dwg_encode_##token (Bit_Chain *restrict dat, \
856 Dwg_Object *restrict obj) \
857 { \
858 int error; \
859 Bit_Chain _hdl_dat = { 0 }; \
860 Bit_Chain *hdl_dat = &_hdl_dat; /* a new copy */ \
861 Bit_Chain *str_dat = dat; /* a ref */ \
862 LOG_INFO ("Encode entity " #token "\n"); \
863 bit_chain_init_dat (hdl_dat, 128, dat); \
864 error = dwg_encode_entity (obj, dat, hdl_dat, str_dat); \
865 if (error) \
866 { \
867 LOG_HANDLE ("Early DWG_ENTITY exit\n"); \
868 if (hdl_dat != dat && hdl_dat->chain != dat->chain) \
869 bit_chain_free (hdl_dat); \
870 return error; \
871 } \
872 error = dwg_encode_##token##_private (dat, hdl_dat, str_dat, obj); \
873 if (error & DWG_ERR_VALUEOUTOFBOUNDS && hdl_dat != dat \
874 && hdl_dat->chain != dat->chain) \
875 { \
876 LOG_HANDLE ("VALUEOUTOFBOUNDS bypassed DWG_ENTITY_END\n"); \
877 /*bit_chain_free (hdl_dat);*/ \
878 } \
879 return error; \
880 } \
881 static int dwg_encode_##token##_private ( \
882 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
883 Dwg_Object *restrict obj) \
884 { \
885 int error = 0; \
886 BITCODE_BL vcount, rcount3, rcount4; \
887 Dwg_Data *dwg = obj->parent; \
888 Dwg_Object_Entity *_ent = obj->tio.entity; \
889 Dwg_Entity_##token *_obj = _ent->tio.token;
890
891 #define DWG_ENTITY_END \
892 if (hdl_dat->byte > dat->byte) \
893 { \
894 dat->byte = hdl_dat->byte; \
895 dat->bit = hdl_dat->bit; \
896 } \
897 if (hdl_dat != dat && hdl_dat->chain != dat->chain) \
898 bit_chain_free (hdl_dat); \
899 return error; \
900 }
901
902 /** Returns -1 if not added, else returns the new objid.
903 Does a complete handleref rescan to invalidate and resolve
904 all internal obj pointers after a object[] realloc.
905 */
906 #define DWG_OBJECT(token) \
907 static int dwg_encode_##token##_private ( \
908 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
909 Dwg_Object *restrict obj); \
910 static int dwg_encode_##token (Bit_Chain *restrict dat, \
911 Dwg_Object *restrict obj) \
912 { \
913 int error; \
914 Bit_Chain _hdl_dat = { 0 }; \
915 Bit_Chain *hdl_dat = &_hdl_dat; /* a new copy */ \
916 Bit_Chain *str_dat = dat; /* a ref */ \
917 LOG_INFO ("Encode object " #token "\n"); \
918 bit_chain_init_dat (hdl_dat, 128, dat); \
919 error = dwg_encode_object (obj, dat, hdl_dat, str_dat); \
920 if (error) \
921 { \
922 if (hdl_dat != dat) \
923 bit_chain_free (hdl_dat); \
924 return error; \
925 } \
926 error = dwg_encode_##token##_private (dat, hdl_dat, str_dat, obj); \
927 if (error & DWG_ERR_VALUEOUTOFBOUNDS && hdl_dat != dat \
928 && hdl_dat->chain != dat->chain) \
929 bit_chain_free (hdl_dat); \
930 return error; \
931 } \
932 static int dwg_encode_##token##_private ( \
933 Bit_Chain *dat, Bit_Chain *hdl_dat, Bit_Chain *str_dat, \
934 Dwg_Object *restrict obj) \
935 { \
936 int error = 0; \
937 BITCODE_BL vcount, rcount3, rcount4; \
938 Dwg_Data *dwg = obj->parent; \
939 Dwg_Object_##token *_obj = obj->tio.object->tio.token;
940
941 // some objects specs forgot about the common streams, so add it here
942 #define DWG_OBJECT_END \
943 if (!obj->hdlpos) \
944 { \
945 START_OBJECT_HANDLE_STREAM \
946 } \
947 if (hdl_dat->byte > dat->byte) \
948 { \
949 dat->byte = hdl_dat->byte; \
950 dat->bit = hdl_dat->bit; \
951 } \
952 if (hdl_dat != dat && hdl_dat->chain != dat->chain) \
953 bit_chain_free (hdl_dat); \
954 return error; \
955 }
956
957 #define ENT_REACTORS(code) \
958 if (dat->version >= R_13 && _obj->num_reactors > 0x1000) \
959 { \
960 LOG_ERROR ("Invalid num_reactors: %ld\n", (long)_obj->num_reactors); \
961 return DWG_ERR_VALUEOUTOFBOUNDS; \
962 } \
963 SINCE (R_13) \
964 { \
965 if (_obj->num_reactors && !_obj->reactors) \
966 { \
967 LOG_ERROR ("NULL entity.reactors"); \
968 return DWG_ERR_VALUEOUTOFBOUNDS; \
969 } \
970 for (vcount = 0; vcount < _obj->num_reactors; vcount++) \
971 { \
972 FIELD_HANDLE_N (reactors[vcount], vcount, code, 330); \
973 } \
974 }
975
976 #undef DEBUG_POS
977 #define DEBUG_POS \
978 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE) \
979 { \
980 LOG_TRACE ("DEBUG_POS @%u.%u / 0x%x (%lu)\n", (unsigned int)dat->byte, \
981 dat->bit, (unsigned int)dat->byte, bit_position (dat)); \
982 }
983
984 /*--------------------------------------------------------------------------------*/
985 typedef struct
986 {
987 unsigned long handle;
988 long address;
989 BITCODE_BL index;
990 } Object_Map;
991
992 /*--------------------------------------------------------------------------------
993 * Private functions prototypes
994 */
995 static int encode_preR13 (Dwg_Data *restrict dwg, Bit_Chain *restrict dat);
996
997 static int dwg_encode_entity (Dwg_Object *restrict obj, Bit_Chain *dat,
998 Bit_Chain *restrict hdl_dat, Bit_Chain *str_dat);
999 static int dwg_encode_object (Dwg_Object *restrict obj, Bit_Chain *dat,
1000 Bit_Chain *restrict hdl_dat, Bit_Chain *str_dat);
1001 static int dwg_encode_common_entity_handle_data (Bit_Chain *dat,
1002 Bit_Chain *hdl_dat,
1003 Dwg_Object *restrict obj);
1004 static int dwg_encode_header_variables (Bit_Chain *dat, Bit_Chain *hdl_dat,
1005 Bit_Chain *str_dat,
1006 Dwg_Data *restrict dwg);
1007 static int dwg_encode_variable_type (Dwg_Data *restrict dwg,
1008 Bit_Chain *restrict dat,
1009 Dwg_Object *restrict obj);
1010 void dwg_encode_handleref (Bit_Chain *hdl_dat, Dwg_Object *restrict obj,
1011 Dwg_Data *restrict dwg,
1012 Dwg_Object_Ref *restrict ref);
1013 void dwg_encode_handleref_with_code (Bit_Chain *hdl_dat,
1014 Dwg_Object *restrict obj,
1015 Dwg_Data *restrict dwg,
1016 Dwg_Object_Ref *restrict ref,
1017 unsigned int code);
1018 int dwg_encode_add_object (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
1019 unsigned long address);
1020
1021 static int dwg_encode_xdata (Bit_Chain *restrict dat,
1022 Dwg_Object_XRECORD *restrict obj, unsigned size);
1023 static unsigned long add_LibreDWG_APPID (Dwg_Data *dwg);
1024 static BITCODE_BL add_DUMMY_eed (Dwg_Object *obj);
1025 static void fixup_NOD (Dwg_Data *restrict dwg, Dwg_Object *restrict obj);
1026
1027 /* Imported */
1028 BITCODE_H
1029 dwg_find_tablehandle_silent (Dwg_Data *restrict dwg, const char *restrict name,
1030 const char *restrict table);
1031 void set_handle_size (Dwg_Handle *restrict hdl);
1032
1033 /*--------------------------------------------------------------------------------
1034 * Public functions
1035 */
1036
1037 static BITCODE_RL
encode_patch_RLsize(Bit_Chain * dat,long unsigned int pvzadr)1038 encode_patch_RLsize (Bit_Chain *dat, long unsigned int pvzadr)
1039 {
1040 unsigned long pos;
1041 BITCODE_RL size;
1042 if (dat->bit) // padding
1043 {
1044 dat->bit = 0;
1045 dat->byte++;
1046 }
1047 size = dat->byte - pvzadr - 4; // minus the RL size
1048 pos = bit_position (dat);
1049 assert (pvzadr);
1050 bit_set_position (dat, pvzadr * 8);
1051 bit_write_RL (dat, size);
1052 LOG_TRACE ("size: " FORMAT_RL " [RL] @%lu\n", size, pvzadr);
1053 bit_set_position (dat, pos);
1054 return size;
1055 }
1056
1057 /* if an error in this section should immediately return with a critical error,
1058 * like INVALIDDWG */
1059 #if 0
1060 static bool
1061 is_section_critical (Dwg_Section_Type i)
1062 {
1063 return (i == SECTION_OBJECTS || i == SECTION_HEADER || i == SECTION_CLASSES
1064 || i == SECTION_HANDLES) ? true : false;
1065 }
1066 #endif
1067 static bool
is_section_r13_critical(Dwg_Section_Type_R13 i)1068 is_section_r13_critical (Dwg_Section_Type_R13 i)
1069 {
1070 return i <= SECTION_HANDLES_R13 ? true : false;
1071 }
1072
1073 /* Limitations: */
1074
1075 static unsigned long
add_LibreDWG_APPID(Dwg_Data * dwg)1076 add_LibreDWG_APPID (Dwg_Data *dwg)
1077 {
1078 BITCODE_H appid = dwg_find_tablehandle_silent (dwg, "LibreDWG", "APPID");
1079 BITCODE_H appctl;
1080 Dwg_Object *obj;
1081 Dwg_Object_APPID *_obj;
1082 Dwg_Object_APPID_CONTROL *o;
1083 unsigned long absref;
1084 //int error = 0;
1085
1086 if (appid)
1087 return appid->absolute_ref;
1088
1089 // This breaks json.test roundtrips tests as it adds a new object.
1090 // But sooner or later we want to delete yet unsupported objects
1091 // (Dictionaries, MATERIAL, VISUALSTYLE, dynblocks, surfaces, assoc*, ...)
1092
1093 // add APPID
1094 #if 1
1095
1096 _obj = dwg_add_APPID (dwg, "LibreDWG");
1097 return dwg_obj_generic_handlevalue (_obj);
1098
1099 #else
1100 if (!(appctl = dwg->header_vars.APPID_CONTROL_OBJECT))
1101 appctl = dwg_find_table_control (dwg, "APPID_CONTROL");
1102 if (!appctl)
1103 {
1104 LOG_ERROR ("APPID_CONTROL not found")
1105 return 0;
1106 }
1107 absref = dwg->object[dwg->num_objects - 1].handle.value + 1;
1108 dwg_add_object (dwg);
1109 obj = &dwg->object[dwg->num_objects - 1];
1110 if (dwg_setup_APPID (obj) >= DWG_ERR_CRITICAL)
1111 return 0;
1112 dwg_add_handle (&obj->handle, 0, absref, obj);
1113 //obj->type = obj->fixedtype = DWG_TYPE_APPID;
1114 _obj = obj->tio.object->tio.APPID;
1115 // precise size, bitsize done by encode
1116 obj->size = 25;
1117 obj->bitsize = 164;
1118 obj->tio.object->ownerhandle = dwg_add_handleref (dwg, 4, appctl->absolute_ref, NULL);
1119 obj->tio.object->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, NULL);
1120
1121 _obj->name = dwg_add_u8_input (dwg, "LibreDWG");
1122 _obj->is_xref_ref = 1;
1123 _obj->xref = dwg_add_handleref (dwg, 5, 0, NULL);
1124
1125 // add to APPID_CONTROL
1126 obj = dwg_ref_object (dwg, appctl);
1127 if (!obj)
1128 {
1129 LOG_ERROR ("APPID_CONTROL not found")
1130 return 0;
1131 }
1132 o = obj->tio.object->tio.APPID_CONTROL;
1133 PUSH_HV (o, num_entries, entries, dwg_add_handleref (dwg, 2, absref, NULL));
1134 return absref;
1135
1136 #endif
1137
1138 return 0x12; // APPID.ACAD
1139 }
1140
1141 static BITCODE_BL
add_DUMMY_eed(Dwg_Object * obj)1142 add_DUMMY_eed (Dwg_Object *obj)
1143 {
1144 Dwg_Object_Entity *ent = obj->tio.entity;
1145 //const int is_entity = obj->supertype == DWG_SUPERTYPE_ENTITY;
1146 const BITCODE_BL num_eed = ent->num_eed; // same offset for object
1147 Dwg_Data *dwg = obj->parent;
1148 char *name = obj->dxfname;
1149 BITCODE_H appid;
1150 Dwg_Eed_Data *data;
1151 int i = 1, off = 0;
1152 int len, size;
1153 const bool is_tu = dwg->header.version >= R_2007;
1154
1155 // FIXME
1156 #ifdef _WIN
1157
1158 return 0;
1159
1160 #else
1161
1162 #ifdef HAVE_STDDEF_H /* windows (mingw32,cygwin) not */
1163 assert (offsetof (Dwg_Object_Object, num_eed) == offsetof (Dwg_Object_Entity, num_eed));
1164 assert (offsetof (Dwg_Object_Object, eed) == offsetof (Dwg_Object_Entity, eed));
1165 #endif
1166
1167 if (num_eed) // replace it
1168 dwg_free_eed (obj);
1169 appid = dwg_find_tablehandle_silent (dwg, "LibreDWG", "APPID");
1170 if (!appid)
1171 {
1172 LOG_WARN ("APPID LibreDWG not found, no EED added");
1173 ent->num_eed = 0;
1174 return 0;
1175 }
1176 ent->num_eed = 1;
1177 ent->eed = calloc (2, sizeof (Dwg_Eed));
1178 len = strlen (name);
1179 size = is_tu ? 1 + 2 + ((len + 1) * 2) // RC + RS_LE + wstr
1180 : 1 + 3 + len + 1; // RC + RC+RS_LE + str
1181 data = ent->eed[0].data = (Dwg_Eed_Data *)calloc (size + 3, 1);
1182 ent->eed[0].size = size;
1183 dwg_add_handle (&ent->eed[0].handle, 5, appid->absolute_ref, NULL);
1184 data->code = 0; // RC
1185 if (is_tu) // probably never used, write DUMMY placeholder to R_2007
1186 {
1187 BITCODE_TU wstr = bit_utf8_to_TU (name, 0);
1188 data->u.eed_0_r2007.is_tu = 1;
1189 data->u.eed_0_r2007.length = len; // RS
1190 memcpy (data->u.eed_0_r2007.string, wstr, len * 2);
1191 }
1192 else
1193 {
1194 data->u.eed_0.is_tu = 0;
1195 data->u.eed_0.length = len; // RC
1196 data->u.eed_0.codepage = 30; // RS
1197 memcpy (data->u.eed_0.string, name, len);
1198 }
1199 LOG_TRACE ("-EED[0]: code: 0, string: %s (len: %d)\n", name, len);
1200
1201 if (!obj->num_unknown_bits)
1202 return 1;
1203 // unknown_bits in chunks of 256
1204 len = obj->num_unknown_bits / 8;
1205 if (obj->num_unknown_bits % 8)
1206 len++;
1207 size = (len / 256) + 1;
1208 if (size > 1) // we already reserved for two eeds
1209 {
1210 ent->eed = realloc (ent->eed, (1 + size) * sizeof (Dwg_Eed));
1211 memset (&ent->eed[1], 0, size * sizeof (Dwg_Eed));
1212 }
1213 do
1214 {
1215 int l = len > 255 ? 255 : len;
1216 ent->num_eed++;
1217 ent->eed[i].size = 0;
1218 ent->eed[0].size += l + 2;
1219 data = ent->eed[i].data = (Dwg_Eed_Data *)calloc (l + 2, 1);
1220 data->code = 4; // RC
1221 data->u.eed_4.length = l; // also just an RC. max 256, how odd
1222 memcpy (data->u.eed_4.data, &obj->unknown_bits[off], data->u.eed_4.length);
1223 LOG_TRACE ("-EED[%d]: code: 4, unknown_bits: %d\n", i, data->u.eed_4.length);
1224 if (len > 255)
1225 {
1226 len -= 256;
1227 off += 256;
1228 i++;
1229 }
1230 else
1231 break;
1232 }
1233 while (1);
1234 return i;
1235 #endif
1236 }
1237
1238 #ifdef ENCODE_UNKNOWN_AS_DUMMY
1239
1240 /** We cannot write unknown bits into another version. Also with indxf we don't
1241 * have that luxury. Write a DUMMY/PLACEHOLDER or POINT instead. Later maybe
1242 * PROXY. This leaks and is controversial. But it silences many ACAD import
1243 * warnings, and preserves information.
1244 */
1245 static void
encode_unknown_as_dummy(Bit_Chain * restrict dat,Dwg_Object * restrict obj,BITCODE_BS placeholder_type)1246 encode_unknown_as_dummy (Bit_Chain *restrict dat, Dwg_Object *restrict obj,
1247 BITCODE_BS placeholder_type)
1248 {
1249 Dwg_Data *dwg = obj->parent;
1250 int is_entity = obj->supertype == DWG_SUPERTYPE_ENTITY;
1251
1252 obj->size = 0;
1253 obj->bitsize = 0;
1254
1255 if (is_entity)
1256 { // POINT is better than DUMMY to preserve the next_entity chain.
1257 // TODO much better would be PROXY_ENTITY
1258 Dwg_Entity_POINT *_obj = obj->tio.entity->tio.POINT;
1259 LOG_WARN ("fixup unsupported %s %lX as POINT", obj->dxfname, obj->handle.value);
1260 if (!obj->tio.entity->xdicobjhandle)
1261 obj->tio.entity->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, NULL);
1262 /*
1263 if (obj->tio.entity->num_reactors)
1264 {
1265 free (obj->tio.entity->reactors);
1266 obj->tio.entity->num_reactors = 0;
1267 obj->tio.entity->reactors = NULL;
1268 }
1269 */
1270 add_DUMMY_eed (obj); // broken on windows
1271 dwg_free_object_private (obj);
1272 free (obj->unknown_bits);
1273 obj->tio.entity->tio.POINT = _obj
1274 = realloc (_obj, sizeof (Dwg_Entity_POINT));
1275 // memset (_obj, 0, sizeof (Dwg_Entity_POINT)); // asan cries
1276 _obj->parent = obj->tio.entity;
1277 _obj->x = 0.0;
1278 _obj->y = 0.0;
1279 _obj->z = 0.0;
1280 _obj->thickness = 1e25; // let it stand out
1281 _obj->extrusion.x = 0.0;
1282 _obj->extrusion.y = 0.0;
1283 _obj->extrusion.z = 1.0;
1284 _obj->x_ang = 0.0;
1285 obj->type = DWG_TYPE_POINT;
1286 obj->fixedtype = DWG_TYPE_POINT;
1287 if (dwg->opts & DWG_OPTS_INJSON)
1288 {
1289 free (obj->name);
1290 obj->name = strdup ("POINT");
1291 }
1292 else
1293 obj->name = (char *)"POINT";
1294 if (dwg->opts & DWG_OPTS_IN)
1295 {
1296 free (obj->dxfname);
1297 obj->dxfname = strdup ("POINT");
1298 }
1299 else
1300 obj->dxfname = (char *)"POINT";
1301 }
1302 else
1303 {
1304 const char *name;
1305 const char *dxfname;
1306
1307 add_DUMMY_eed (obj); // broken on windows
1308 dwg_free_object_private (obj);
1309 // if PLACEHOLDER is available, or even PROXY_OBJECT.
1310 // PLOTSETTINGS uses PLACEHOLDER though
1311 if (placeholder_type)
1312 {
1313 obj->type = placeholder_type;
1314 obj->fixedtype = DWG_TYPE_PLACEHOLDER;
1315 name = "PLACEHOLDER";
1316 dxfname = "ACDBPLACEHOLDER";
1317 }
1318 else
1319 {
1320 obj->type = DWG_TYPE_DUMMY;
1321 obj->fixedtype = DWG_TYPE_DUMMY;
1322 name = "DUMMY";
1323 dxfname = "DUMMY";
1324 }
1325 LOG_INFO ("fixup unsupported %s %lX as %s, Type %d\n", obj->dxfname,
1326 obj->handle.value, name, obj->type);
1327 if (!obj->tio.object->xdicobjhandle)
1328 obj->tio.object->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, NULL);
1329 // keep owner, xdicobj, reactors
1330 if (dwg->opts & DWG_OPTS_INJSON)
1331 {
1332 free (obj->name);
1333 obj->name = strdup (name);
1334 }
1335 else
1336 obj->name = (char *)name;
1337 if (dwg->opts & DWG_OPTS_IN)
1338 {
1339 free (obj->dxfname);
1340 obj->dxfname = strdup (dxfname);
1341 }
1342 else
1343 obj->dxfname = (char *)dxfname;
1344 free (obj->unknown_bits);
1345 }
1346 obj->hdlpos = 0;
1347 }
1348 #endif
1349
1350 // delete this NOD entry
1351 // only needed until we can write all object types (at least the ones from the NOD)
1352 static void
remove_NOD_item(Dwg_Object_DICTIONARY * _obj,const int i,const char * name)1353 remove_NOD_item (Dwg_Object_DICTIONARY *_obj, const int i, const char *name)
1354 {
1355 int last = _obj->numitems - 1;
1356 LOG_TRACE ("Disable link to " FORMAT_REF " for NOD.%s\n",
1357 ARGS_REF (_obj->itemhandles[i]), name);
1358 if (i < last)
1359 {
1360 free (_obj->texts[i]);
1361 if (!_obj->itemhandles[i]->handleref.is_global)
1362 free (_obj->itemhandles[i]);
1363 memmove (&_obj->texts[i], &_obj->texts[i+1], (last - i) * sizeof (BITCODE_T));
1364 memmove (&_obj->itemhandles[i], &_obj->itemhandles[i+1], (last - i) * sizeof (BITCODE_H));
1365 }
1366 _obj->numitems--;
1367 return;
1368 }
1369
1370 // NOD: ACAD_TABLESTYLE => DICT name[0] - itemhandles[0] => TABLESTYLE (Unstable)
1371 // AcDbVariableDictionary: CTABLESTYLE => DICTVAR str
1372 // only needed until we can write all object types (at least the ones from the NOD)
1373 static void
fixup_NOD(Dwg_Data * restrict dwg,Dwg_Object * restrict obj)1374 fixup_NOD (Dwg_Data *restrict dwg, Dwg_Object *restrict obj) // named object dict
1375 {
1376 Dwg_Object_DICTIONARY *_obj;
1377 int is_tu = dwg->header.version >= R_2007;
1378 if (obj->handle.value != 0xC)
1379 return;
1380 _obj = obj->tio.object->tio.DICTIONARY;
1381 // => DICTIONARY with name of current style, and link to it.
1382 // If the link target is disabled (unstable, unhandled or such), remove it from the NOD.
1383 #define DISABLE_NODSTYLE(name) \
1384 if (!is_type_stable (DWG_TYPE_##name)) \
1385 { \
1386 if (is_tu) \
1387 { \
1388 char *u8 = bit_convert_TU ((BITCODE_TU)_obj->texts[i]); \
1389 if (u8 && strEQc (u8, "ACAD_" #name)) \
1390 remove_NOD_item (_obj, i, "ACAD_" #name); \
1391 free (u8); \
1392 } \
1393 else if (_obj->texts[i] && strEQc (_obj->texts[i], "ACAD_" #name)) \
1394 remove_NOD_item (_obj, i, "ACAD_" #name); \
1395 }
1396
1397 for (BITCODE_BL i = 0; i < _obj->numitems; i++)
1398 {
1399 DISABLE_NODSTYLE (ASSOCNETWORK)
1400 else DISABLE_NODSTYLE (ASSOCPERSSUBENTMANAGER)
1401 else DISABLE_NODSTYLE (DETAILVIEWSTYLE)
1402 else DISABLE_NODSTYLE (MATERIAL)
1403 else DISABLE_NODSTYLE (MLEADERSTYLE)
1404 else DISABLE_NODSTYLE (MLINESTYLE)
1405 else DISABLE_NODSTYLE (PERSUBENTMGR)
1406 else DISABLE_NODSTYLE (PLOTSETTINGS)
1407 // else DISABLE_NODSTYLE (PLOTSTYLENAME)
1408 else DISABLE_NODSTYLE (SECTIONVIEWSTYLE)
1409 else DISABLE_NODSTYLE (TABLESTYLE)
1410 else DISABLE_NODSTYLE (VISUALSTYLE)
1411 }
1412 #undef DISABLE_NODSTYLE
1413 }
1414
1415 /* Copy the decomp buffer uncompressed into dat of a DWG r2004+ file. Sets comp_data_size. */
copy_R2004_section(Bit_Chain * restrict dat,BITCODE_RC * restrict decomp,uint32_t decomp_data_size,uint32_t * comp_data_size)1416 static int copy_R2004_section (Bit_Chain *restrict dat, BITCODE_RC *restrict decomp,
1417 uint32_t decomp_data_size, uint32_t *comp_data_size)
1418 {
1419 if (dat->byte + decomp_data_size >= dat->size)
1420 {
1421 dat->size = dat->byte + decomp_data_size;
1422 bit_chain_alloc (dat);
1423 }
1424 assert (!dat->bit);
1425 memcpy (&dat->chain[dat->byte], decomp, decomp_data_size);
1426 dat->byte += decomp_data_size;
1427 *comp_data_size = decomp_data_size;
1428 return 0;
1429 }
1430
1431 /* 1 for yes, 0 for no */
1432 static int
section_encrypted(const Dwg_Data * dwg,const Dwg_Section_Type id)1433 section_encrypted (const Dwg_Data *dwg, const Dwg_Section_Type id)
1434 {
1435 switch (id)
1436 {
1437 case SECTION_SECURITY: //??
1438 case SECTION_FILEDEPLIST:
1439 case SECTION_APPINFO:
1440 return 1;
1441 case SECTION_UNKNOWN:
1442 case SECTION_HEADER:
1443 case SECTION_REVHISTORY:
1444 case SECTION_OBJECTS:
1445 case SECTION_OBJFREESPACE:
1446 case SECTION_TEMPLATE:
1447 case SECTION_HANDLES:
1448 case SECTION_CLASSES:
1449 case SECTION_AUXHEADER:
1450 case SECTION_SUMMARYINFO:
1451 case SECTION_PREVIEW:
1452 case SECTION_APPINFOHISTORY:
1453 case SECTION_VBAPROJECT:
1454 case SECTION_SIGNATURE:
1455 case SECTION_ACDS:
1456 case SECTION_SYSTEM_MAP:
1457 case SECTION_INFO:
1458 default:
1459 return 0;
1460 }
1461 }
1462
1463 /* 1 for yes, 0 for no */
1464 static int
section_compressed(const Dwg_Data * dwg,const Dwg_Section_Type id)1465 section_compressed (const Dwg_Data *dwg, const Dwg_Section_Type id)
1466 {
1467 switch (id)
1468 {
1469 case SECTION_UNKNOWN:
1470 case SECTION_HEADER:
1471 case SECTION_REVHISTORY:
1472 case SECTION_OBJECTS:
1473 case SECTION_OBJFREESPACE:
1474 case SECTION_TEMPLATE:
1475 case SECTION_HANDLES:
1476 case SECTION_CLASSES:
1477 case SECTION_AUXHEADER:
1478 case SECTION_SYSTEM_MAP:
1479 case SECTION_INFO:
1480 return 1;
1481 case SECTION_SUMMARYINFO:
1482 case SECTION_PREVIEW:
1483 case SECTION_APPINFO:
1484 case SECTION_APPINFOHISTORY:
1485 case SECTION_FILEDEPLIST:
1486 case SECTION_SECURITY:
1487 case SECTION_VBAPROJECT:
1488 case SECTION_SIGNATURE:
1489 case SECTION_ACDS:
1490 default:
1491 return 0;
1492 }
1493 }
1494
1495 /* r2004 compressed sections, LZ77 WIP */
1496
1497 #define MIN_COMPRESSED_SECTION 19
1498 #define COMPRESSION_BUFFER_SIZE 0x400
1499 #define COMPRESSION_WINDOW_SIZE 0x800
1500
1501 static void
1502 write_length (Bit_Chain *dat, uint32_t u1, uint32_t match, uint32_t u2);
1503
1504 /* R2004 Write literal length
1505 */
1506 static unsigned char
write_literal_length(Bit_Chain * restrict dat,BITCODE_RC * restrict buf,uint32_t len)1507 write_literal_length (Bit_Chain *restrict dat, BITCODE_RC *restrict buf, uint32_t len)
1508 {
1509 #if 0
1510 if (len <= (0x0F + 3)) // single byte, opcode 0
1511 {
1512 bit_write_RC (dat, len - 3);
1513 return 0;
1514 }
1515 else if (len < 0xf0)
1516 {
1517 bit_write_RC (dat, len);
1518 return length & 0xff;
1519 }
1520 else
1521 {
1522 uint32_t total = 0x0f;
1523 while (leng >= 0xf0)
1524 {
1525 bit_write_RC (dat, 0);
1526 len -= 0xFF;
1527 total += 0xFF;
1528 }
1529 bit_write_RC (dat, len - 3); // ??
1530 return 0;
1531 }
1532 #else
1533 if (len)
1534 {
1535 if (len > 3) {
1536 write_length (dat, 0, len - 1, 0x11);
1537 }
1538 LOG_INSANE ("LIT %x\n", len)
1539 bit_write_TF (dat, buf, len);
1540 }
1541 return 0;
1542 #endif
1543 }
1544
1545 /* R2004 Long Compression Offset
1546 */
1547 static void
write_long_compression_offset(Bit_Chain * dat,uint32_t offset)1548 write_long_compression_offset (Bit_Chain *dat, uint32_t offset)
1549 {
1550 while (offset > 0xff)
1551 {
1552 bit_write_RC (dat, 0);
1553 offset -= 0xff;
1554 }
1555 LOG_INSANE (">O 00 %x", offset)
1556 bit_write_RC (dat, (unsigned char)offset);
1557 }
1558
1559 static void
write_length(Bit_Chain * dat,uint32_t u1,uint32_t match,uint32_t u2)1560 write_length (Bit_Chain *dat, uint32_t u1, uint32_t match, uint32_t u2)
1561 {
1562 if (u2 < match)
1563 {
1564 LOG_INSANE (">L %x ", u1 & 0xff)
1565 bit_write_RC (dat, u1 & 0xff);
1566 write_long_compression_offset (dat, match - u2);
1567 LOG_INSANE ("\n")
1568 }
1569 else
1570 {
1571 LOG_INSANE (">L %x\n", (u1 | (match - 2)) & 0xff);
1572 bit_write_RC (dat, (u1 | (match - 2)) & 0xff);
1573 }
1574 }
1575
1576 /* R2004 Two Byte Offset
1577 */
1578 #if 0
1579 static unsigned int
1580 write_two_byte_offset (Bit_Chain *restrict dat, uint32_t offset)
1581 {
1582 BITCODE_RC b1, b2;
1583 b1 = offset << 2;
1584 b2 = offset >> 6;
1585 //offset = (firstByte >> 2) | (secondByte << 6);
1586 bit_write_RC (dat, b1);
1587 bit_write_RC (dat, b2);
1588 //*lit_length = (firstByte & 0x03);
1589 return b1 & 0x03;
1590 }
1591 #endif
1592
1593 static void
write_two_byte_offset(Bit_Chain * restrict dat,uint32_t oldlen,uint32_t offset,uint32_t len)1594 write_two_byte_offset (Bit_Chain *restrict dat, uint32_t oldlen, uint32_t offset, uint32_t len)
1595 {
1596 const unsigned lookahead_buffer_size = COMPRESSION_BUFFER_SIZE;
1597 uint32_t b1, b2;
1598
1599 LOG_INSANE ("2O %x %x %x: ", oldlen, offset, len)
1600 if ((offset < 0xf) && (oldlen < 0x401))
1601 {
1602 b1 = (offset + 1) * 0x10 | ((oldlen - 1U) & 3) << 2;
1603 b2 = (oldlen - 1U) >> 2;
1604 }
1605 else
1606 {
1607 if (oldlen <= lookahead_buffer_size)
1608 {
1609 b2 = oldlen - 1;
1610 write_length (dat, 0x20, offset, 0x21);
1611 }
1612 else
1613 {
1614 b2 = oldlen - lookahead_buffer_size;
1615 write_length (dat, ((b2 >> 0xb) & 8U) | 0x10, offset, 9);
1616 }
1617 b1 = (b2 & 0xff) << 2;
1618 b2 = b2 >> 6;
1619 }
1620 if (len < 4)
1621 b1 = b1 | len;
1622 LOG_INSANE ("> %x %x\n", b1, b2)
1623 bit_write_RC (dat, b1 & 0xff);
1624 bit_write_RC (dat, b2 & 0xff);
1625 }
1626
1627 /* Finds the longest match to the substring starting at i
1628 in the lookahead buffer (size ?) from the history window (size ?). */
1629 static int
find_longest_match(BITCODE_RC * restrict decomp,uint32_t decomp_data_size,uint32_t i,uint32_t * lenp)1630 find_longest_match (BITCODE_RC *restrict decomp, uint32_t decomp_data_size, uint32_t i, uint32_t *lenp)
1631 {
1632 const unsigned lookahead_buffer_size = COMPRESSION_BUFFER_SIZE;
1633 const unsigned window_size = COMPRESSION_WINDOW_SIZE;
1634 int offset = 0;
1635 uint32_t bufend = MIN (i + lookahead_buffer_size, decomp_data_size + 1);
1636 *lenp = 0;
1637 // only substring lengths >= 2, anything else compression is longer
1638 for (uint32_t j = i + 2; j < bufend; j++)
1639 {
1640 int start = MAX (0, (int)(i - window_size));
1641 BITCODE_RC *s = &decomp[i];
1642 uint32_t slen = j - i;
1643 for (int k = start; k < (int)i; k++)
1644 {
1645 int curr_offset = i - k;
1646 //unsigned int repetitions = slen / curr_offset;
1647 //unsigned int last = slen % curr_offset;
1648 BITCODE_RC *match = &decomp[k]; // ...
1649 //int matchlen = k + last;
1650 if ((memcmp (s, match, slen) == 0)
1651 && slen > *lenp)
1652 {
1653 offset = curr_offset;
1654 *lenp = slen;
1655 }
1656 }
1657 }
1658 if (offset)
1659 {
1660 LOG_INSANE (">M %u (%u)\n", offset, *lenp)
1661 }
1662 return offset;
1663 }
1664
1665 /* Compress the decomp buffer into dat of a DWG r2004+ file. Sets comp_data_size.
1666 Variant of the LZ77 algo. ODA section 4.7
1667 */
compress_R2004_section(Bit_Chain * restrict dat,BITCODE_RC * restrict decomp,uint32_t decomp_data_size,uint32_t * comp_data_size)1668 static int compress_R2004_section (Bit_Chain *restrict dat, BITCODE_RC *restrict decomp,
1669 uint32_t decomp_data_size, uint32_t *comp_data_size)
1670 {
1671 uint32_t i = 0;
1672 uint32_t match = 0, oldlen = 0;
1673 uint32_t len = 0;
1674 unsigned long pos = bit_position (dat);
1675 LOG_WARN ("compress_R2004_section %d", decomp_data_size);
1676 assert (decomp_data_size > MIN_COMPRESSED_SECTION);
1677 while (i < decomp_data_size - MIN_COMPRESSED_SECTION)
1678 {
1679 int offset = find_longest_match (decomp, decomp_data_size, i, &len);
1680 if (offset)
1681 {
1682 // encode offset + len
1683 if (match)
1684 write_two_byte_offset (dat, oldlen, match, len);
1685 write_literal_length (dat, &decomp[i], len);
1686 i += match;
1687 match = offset;
1688 oldlen = len;
1689 }
1690 else
1691 {
1692 i += 1; // no match found
1693 }
1694 }
1695 len = decomp_data_size - i;
1696 if (match)
1697 write_two_byte_offset (dat, oldlen, match, len);
1698 write_literal_length (dat, &decomp[i], len);
1699 bit_write_RC (dat, 0x11);
1700 bit_write_RC (dat, 0);
1701 bit_write_RC (dat, 0);
1702 *comp_data_size = bit_position (dat) - pos;
1703 LOG_INSANE ("> 11 0 => %u\n", *comp_data_size)
1704 return 0;
1705 }
1706
1707 static Dwg_Section_Info *
find_section_info_type(const Dwg_Data * restrict dwg,Dwg_Section_Type type)1708 find_section_info_type (const Dwg_Data *restrict dwg, Dwg_Section_Type type)
1709 {
1710 for (unsigned i = 0; i < dwg->header.section_infohdr.num_desc; i++)
1711 {
1712 Dwg_Section_Info *info = &dwg->header.section_info[i];
1713 if (info->fixedtype == type)
1714 return info;
1715 }
1716 return NULL;
1717 }
1718
1719 /* header.section pointers changed, rebuild all info->sections */
1720 static void
section_info_rebuild(Dwg_Data * dwg,Dwg_Section_Type lasttype)1721 section_info_rebuild (Dwg_Data *dwg, Dwg_Section_Type lasttype)
1722 {
1723 Dwg_Section_Type type;
1724 // we only need to rebuild sections up to the given type
1725 for (type = 0; type <= lasttype; type++)
1726 {
1727 Dwg_Section_Info *info = find_section_info_type (dwg, type);
1728 if (info)
1729 {
1730 unsigned ssi = 0;
1731 for (unsigned i = 0; i < dwg->header.num_sections; i++)
1732 {
1733 Dwg_Section *sec = &dwg->header.section[i];
1734 if (sec->type == type) // first section
1735 {
1736 info->sections[ssi] = sec;
1737 ssi++;
1738 }
1739 else if (sec->type > type) // sorted by type
1740 break;
1741 }
1742 }
1743 }
1744 }
1745
1746 /**
1747 * dwg_encode(): the current generic encoder entry point.
1748 *
1749 * TODO: preR13 tables, 2007 maps.
1750 * 2010+ uses the 2004 format.
1751 * Returns a summary bitmask of all errors.
1752 */
1753 AFL_GCC_TOOBIG
1754 EXPORT int
dwg_encode(Dwg_Data * restrict dwg,Bit_Chain * restrict dat)1755 dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat)
1756 {
1757 int ckr_missing = 1;
1758 int error = 0;
1759 BITCODE_BL i, j;
1760 long unsigned int section_address;
1761 long unsigned int pvzadr;
1762 unsigned int ckr;
1763 unsigned int sec_size = 0;
1764 long unsigned int last_offset;
1765 BITCODE_BL last_handle;
1766 Object_Map *omap;
1767 Bit_Chain *old_dat = NULL, *str_dat, *hdl_dat;
1768 int sec_id;
1769 Dwg_Version_Type orig_from_version = dwg->header.from_version;
1770 Bit_Chain sec_dat[SECTION_SYSTEM_MAP + 1]; // to encode each r2004 section
1771
1772 if (dwg->opts)
1773 loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
1774 #ifdef USE_TRACING
1775 /* Before starting, set the logging level, but only do so once. */
1776 if (!env_var_checked_p)
1777 {
1778 char *probe = getenv ("LIBREDWG_TRACE");
1779 if (probe)
1780 loglevel = atoi (probe);
1781 env_var_checked_p = true;
1782 }
1783 #endif /* USE_TRACING */
1784
1785 if (dwg->header.version != dwg->header.from_version)
1786 LOG_TRACE ("Encode version %s (%s) from version %s (%s)\n",
1787 version_codes[dwg->header.version],
1788 dwg_version_type (dwg->header.version),
1789 version_codes[dwg->header.from_version],
1790 dwg_version_type (dwg->header.from_version))
1791 else
1792 LOG_TRACE ("Encode version %s (%s)\n", version_codes[dwg->header.version],
1793 dwg_version_type (dwg->header.version))
1794
1795 #ifdef ENCODE_UNKNOWN_AS_DUMMY
1796 // We cannot write unknown_bits into another version, or when it's coming
1797 // from DXF. Write a PLACEHOLDER/DUMMY or POINT instead. Later maybe PROXY.
1798 // This is controversial and breaks roundtrip tests, but helps
1799 // ACAD imports.
1800 if (dwg->header.version != dwg->header.from_version
1801 || (dwg->opts & DWG_OPTS_IN))
1802 {
1803 int fixup = 0;
1804 // Scan for invalid/unstable/unsupported objects and entities
1805 // and eliminate or replace them with placeholders.
1806 LOG_TRACE ("Scan for unsupported objects\n");
1807 for (i = 0; i < dwg->num_objects; i++)
1808 {
1809 Dwg_Object *obj = &dwg->object[i];
1810 if (obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ
1811 || obj->fixedtype == DWG_TYPE_UNKNOWN_ENT
1812 // WIPEOUT causes hang, TABLEGEOMETRY crash
1813 || (dwg->opts & DWG_OPTS_IN &&
1814 (obj->fixedtype == DWG_TYPE_WIPEOUT ||
1815 obj->fixedtype == DWG_TYPE_TABLEGEOMETRY)))
1816 {
1817 fixup++;
1818 break;
1819 }
1820 }
1821 if (fixup)
1822 {
1823 unsigned long new_appid;
1824 BITCODE_BS placeholder_type = 0;
1825 LOG_TRACE ("Found unsupported objects, add APPID LibreDWG\n");
1826 new_appid = add_LibreDWG_APPID (dwg);
1827 if (new_appid)
1828 {
1829 fixup = 0;
1830 // if not found leaves placeholder_type at 0 to use DUMMY
1831 dwg_find_class (dwg, "ACDBPLACEHOLDER", &placeholder_type);
1832 for (i = 0; i < dwg->num_objects; i++)
1833 {
1834 Dwg_Object *obj = &dwg->object[i];
1835 if (obj->fixedtype == DWG_TYPE_UNKNOWN_OBJ
1836 || obj->fixedtype == DWG_TYPE_UNKNOWN_ENT
1837 || (dwg->opts & DWG_OPTS_IN &&
1838 (obj->fixedtype == DWG_TYPE_WIPEOUT ||
1839 obj->fixedtype == DWG_TYPE_TABLEGEOMETRY)))
1840 {
1841 fixup++;
1842 // replace entities with points, objects with
1843 // placeholders
1844 encode_unknown_as_dummy (dat, obj, placeholder_type);
1845 }
1846 // what to do with links to MATERIAL/...
1847 if (obj->handle.value == 0xC
1848 && obj->fixedtype == DWG_TYPE_DICTIONARY)
1849 fixup_NOD (dwg, obj); // named object dict
1850 }
1851 LOG_TRACE ("Fixed %d unsupported objects\n\n", fixup);
1852 }
1853 }
1854 }
1855 #endif
1856
1857 bit_chain_alloc (dat);
1858 hdl_dat = dat; // splitted later in objects/entities
1859 if (!dat->version)
1860 {
1861 dat->version = dwg->header.version;
1862 dat->from_version = dwg->header.from_version;
1863 dat->opts = dwg->opts;
1864 }
1865
1866 /*------------------------------------------------------------
1867 * Header
1868 */
1869 strcpy ((char *)dat->chain,
1870 version_codes[dwg->header.version]); // Chain version
1871 dat->byte += 6;
1872
1873 {
1874 Dwg_Header *_obj = &dwg->header;
1875 Dwg_Object *obj = NULL;
1876 if (!_obj->dwg_version) // ie from DXF
1877 {
1878 _obj->zero_one_or_three = 1;
1879 _obj->dwg_version = 0x21;
1880 _obj->is_maint = 0xf;
1881 _obj->maint_version = 29;
1882 if (dwg->header.version < R_13)
1883 {
1884 _obj->dwg_version = 0x14;
1885 }
1886 /*
1887 switch (dwg->header.version)
1888 {
1889 case R_9:
1890 _obj->dwg_version = 0x0b;
1891 break;
1892 case R_10:
1893 _obj->dwg_version = 0x0d;
1894 break;
1895 case R_11:
1896 _obj->dwg_version = 0x10;
1897 break;
1898 case R_13:
1899 _obj->dwg_version = 0x13;
1900 break;
1901 case R_13c3:
1902 _obj->dwg_version = 0x14;
1903 break;
1904 case R_14:
1905 _obj->dwg_version = 0x15;
1906 break;
1907 case R_2000:
1908 _obj->dwg_version = 0x17;
1909 _obj->is_maint = 0xf;
1910 break;
1911 case R_2004:
1912 _obj->dwg_version = 0x19; // or 0x18/0x1a
1913 _obj->is_maint = 0x68;
1914 break;
1915 case R_2007:
1916 _obj->dwg_version = 0x1b;
1917 _obj->is_maint = 0x32;
1918 break;
1919 case R_2010:
1920 _obj->dwg_version = 0x1d;
1921 _obj->is_maint = 0x6d;
1922 break;
1923 case R_2013:
1924 _obj->dwg_version = 0x1f;
1925 _obj->is_maint = 0x7d;
1926 break;
1927 case R_2018:
1928 _obj->dwg_version = 0x21;
1929 _obj->is_maint = 0x1d;
1930 break;
1931 case R_INVALID:
1932 case R_AFTER:
1933 case R_1_1:
1934 case R_1_2:
1935 case R_1_3:
1936 case R_1_4:
1937 case R_1_402b:
1938 case R_2_0:
1939 case R_2_1:
1940 case R_2_21:
1941 case R_2_22:
1942 case R_2_4:
1943 case R_2_5:
1944 case R_2_6:
1945 case R_9c1:
1946 case R_10c1:
1947 case R_10c2:
1948 case R_12:
1949 case R_12c1:
1950 default:
1951 break;
1952 }
1953 */
1954 if (!_obj->app_dwg_version)
1955 _obj->app_dwg_version = _obj->dwg_version;
1956 }
1957 if (!_obj->codepage)
1958 _obj->codepage = 30;
1959
1960 // clang-format off
1961 #include "header.spec"
1962 // clang-format on
1963 }
1964 section_address = dat->byte;
1965
1966 #define WE_CAN \
1967 "This version of LibreDWG is only capable of encoding " \
1968 "version R13-R2000 (code: AC1012-AC1015) DWG files.\n"
1969
1970 PRE (R_13)
1971 {
1972 // TODO: tables, entities, block entities
1973 LOG_ERROR (WE_CAN "We don't encode preR13 tables, entities, blocks yet")
1974 #ifndef IS_RELEASE
1975 return encode_preR13 (dwg, dat);
1976 #endif
1977 }
1978
1979 PRE (R_2004)
1980 {
1981 /* section 0: header vars
1982 * 1: class section
1983 * 2: object map
1984 * 3: (R13 c3 and later): 2nd header (special table no sentinels)
1985 * 4: optional: MEASUREMENT
1986 * 5: optional: AuxHeader
1987 */
1988 /* Usually 3-5, max 6 */
1989 if (!dwg->header.num_sections
1990 || (dat->from_version >= R_2004 && dwg->header.num_sections > 6))
1991 {
1992 dwg->header.num_sections = dwg->header.version < R_2000 ? 5 : 6;
1993 // minimal DXF:
1994 if (!dwg->header_vars.HANDSEED || !dwg->header_vars.TDCREATE.days)
1995 {
1996 dwg->header.num_sections = 5;
1997 // hack to trigger IF_ENCODE_FROM_EARLIER defaults. undone after
1998 // HEADER
1999 dat->from_version = R_11;
2000 if (dat->version <= dat->from_version)
2001 dat->from_version = (Dwg_Version_Type)((int)dat->version - 1);
2002 }
2003 }
2004 LOG_TRACE ("num_sections: " FORMAT_RL " [RL]\n", dwg->header.num_sections);
2005 bit_write_RL (dat, dwg->header.num_sections);
2006 if (!dwg->header.section)
2007 dwg->header.section = (Dwg_Section*)calloc (dwg->header.num_sections,
2008 sizeof (Dwg_Section));
2009 if (!dwg->header.section)
2010 {
2011 LOG_ERROR ("Out of memory");
2012 return DWG_ERR_OUTOFMEM;
2013 }
2014 section_address = dat->byte; // save section address
2015 dat->byte += (dwg->header.num_sections * 9); /* RC + 2*RL */
2016 bit_write_CRC (dat, 0, 0xC0C1);
2017 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_HEADER_END));
2018
2019 /*------------------------------------------------------------
2020 * AuxHeader section 5
2021 * R2000+, mostly redundant file header information
2022 */
2023 if (dwg->header.num_sections > 5)
2024 {
2025 Dwg_AuxHeader *_obj = &dwg->auxheader;
2026 Dwg_Object *obj = NULL;
2027 BITCODE_BL vcount;
2028 assert (!dat->bit);
2029 LOG_INFO ("\n=======> AuxHeader: %8u\n",
2030 (unsigned)dat->byte); // size: 123
2031
2032 dwg->header.section[SECTION_AUXHEADER_R2000].number = 5;
2033 dwg->header.section[SECTION_AUXHEADER_R2000].address = dat->byte;
2034
2035 if (!_obj->dwg_version) // todo: needed?
2036 {
2037 BITCODE_RS def_unknown_6rs[] = { 4, 0x565, 0, 0, 2, 1 };
2038 LOG_TRACE ("Use AuxHeader defaults...\n");
2039 FIELD_VALUE (aux_intro[0]) = 0xff;
2040 FIELD_VALUE (aux_intro[1]) = 0x77;
2041 FIELD_VALUE (aux_intro[2]) = 0x01;
2042 FIELD_VALUE (minus_1) = -1;
2043 FIELD_VALUE (dwg_version) = dwg->header.dwg_version;
2044 FIELD_VALUE (maint_version) = dwg->header.maint_version;
2045 FIELD_VALUE (dwg_version_1) = dwg->header.dwg_version;
2046 FIELD_VALUE (dwg_version_2) = dwg->header.dwg_version;
2047 FIELD_VALUE (maint_version_1) = dwg->header.maint_version;
2048 FIELD_VALUE (maint_version_2) = dwg->header.maint_version;
2049 memcpy (FIELD_VALUE (unknown_6rs), def_unknown_6rs,
2050 sizeof (def_unknown_6rs));
2051 FIELD_VALUE (TDCREATE) = dwg->header_vars.TDCREATE.value;
2052 FIELD_VALUE (TDUPDATE) = dwg->header_vars.TDUPDATE.value;
2053 if (dwg->header_vars.HANDSEED)
2054 FIELD_VALUE (HANDSEED) = dwg->header_vars.HANDSEED->absolute_ref;
2055 }
2056
2057 // clang-format off
2058 #include "auxheader.spec"
2059 // clang-format on
2060
2061 assert (!dat->bit);
2062 dwg->header.section[SECTION_AUXHEADER_R2000].size
2063 = dat->byte - dwg->header.section[SECTION_AUXHEADER_R2000].address;
2064 }
2065 }
2066
2067 VERSION (R_2007)
2068 {
2069 LOG_ERROR (WE_CAN "We don't encode R2007 sections yet");
2070 dat->version = dwg->header.version = R_2010; // rather do 2010
2071 // return DWG_ERR_NOTYETSUPPORTED;
2072 }
2073
2074 /* r2004 file header (compressed + encrypted) */
2075 SINCE (R_2004)
2076 {
2077 LOG_INFO ("\n");
2078 LOG_ERROR (WE_CAN "Writing R2004 sections not yet finished");
2079
2080 memset (&sec_dat, 0, (SECTION_SYSTEM_MAP + 1) * sizeof (Bit_Chain));
2081 if (dwg->header.section_infohdr.num_desc && !dwg->header.section_info)
2082 dwg->header.section_info = (Dwg_Section_Info *)calloc (
2083 dwg->header.section_infohdr.num_desc, sizeof (Dwg_Section_Info));
2084 LOG_TRACE ("\n#### r2004 File Header ####\n");
2085 if (dat->byte + 0x80 >= dat->size - 1)
2086 {
2087 dwg->header.num_sections = 28; // room for some object pages
2088 dwg->header.section = calloc (28, sizeof (Dwg_Section));
2089 }
2090 if (!dwg->header.section_info)
2091 {
2092 dwg->header.section_infohdr.num_desc = SECTION_SYSTEM_MAP + 1;
2093 dwg->header.section_info
2094 = calloc (SECTION_SYSTEM_MAP + 1, sizeof (Dwg_Section_Info));
2095 }
2096 }
2097
2098 /*------------------------------------------------------------
2099 * THUMBNAIL preview pictures
2100 */
2101 old_dat = dat;
2102 SINCE (R_2004)
2103 {
2104 bit_chain_init_dat (&sec_dat[SECTION_PREVIEW], dwg->thumbnail.size + 64, dat);
2105 str_dat = hdl_dat = dat = &sec_dat[SECTION_PREVIEW];
2106 }
2107 else
2108 {
2109 if (!dwg->header.thumbnail_address)
2110 dwg->header.thumbnail_address = dat->byte;
2111 }
2112 dat->bit = 0;
2113 LOG_TRACE ("\n=======> Thumbnail: %4u\n", (unsigned)dat->byte);
2114 // dwg->thumbnail.size = 0; // to disable
2115 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_BEGIN));
2116 if (dwg->thumbnail.size == 0)
2117 {
2118 bit_write_RL (dat, 5); // overall size
2119 LOG_TRACE ("Thumbnail size: 5 [RL]\n");
2120 bit_write_RC (dat, 0); // num_pictures
2121 LOG_TRACE ("Thumbnail num_pictures: 0 [RC]\n");
2122 }
2123 else
2124 {
2125 bit_write_TF (dat, dwg->thumbnail.chain, dwg->thumbnail.size);
2126 }
2127 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_THUMBNAIL_END));
2128
2129 {
2130 BITCODE_RL bmpsize;
2131 dwg_bmp (dwg, &bmpsize);
2132 if (bmpsize > dwg->thumbnail.size)
2133 LOG_ERROR ("BMP size overflow: %i > %lu\n", bmpsize,
2134 dwg->thumbnail.size);
2135 }
2136 LOG_TRACE (" Thumbnail (end): %4u\n", (unsigned)dat->byte);
2137
2138 /*------------------------------------------------------------
2139 * Header Variables
2140 */
2141 SINCE (R_2004)
2142 {
2143 sec_id = SECTION_HEADER;
2144 bit_chain_init_dat (&sec_dat[sec_id], sizeof (Dwg_Header) + 64, dat);
2145 str_dat = hdl_dat = dat = &sec_dat[sec_id];
2146 }
2147 assert (!dat->bit);
2148 LOG_INFO ("\n=======> Header Variables: %4u\n", (unsigned)dat->byte);
2149 if (!dwg->header.section)
2150 {
2151 LOG_ERROR ("Empty header.section");
2152 return DWG_ERR_OUTOFMEM;
2153 }
2154 dwg->header.section[0].number = 0;
2155 dwg->header.section[0].address = dat->byte;
2156 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_VARIABLE_BEGIN));
2157
2158 pvzadr = dat->byte; // Size position
2159 bit_write_RL (dat, 540); // Size placeholder
2160 // if (dat->version >= R_2007)
2161 // str_dat = dat;
2162 dwg_encode_header_variables (dat, hdl_dat, dat, dwg);
2163 // undo minimal HEADER hack
2164 if (dat->from_version != orig_from_version)
2165 dat->from_version = orig_from_version;
2166 encode_patch_RLsize (dat, pvzadr);
2167 bit_write_CRC (dat, pvzadr, 0xC0C1);
2168
2169 // XXX trying to fix CRC 2-byte overflow. Must find actual reason.
2170 // dat->byte -= 2;
2171 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_VARIABLE_END));
2172 assert ((long)dat->byte > (long)dwg->header.section[0].address);
2173 dwg->header.section[0].size
2174 = (BITCODE_RL) ((long)dat->byte - (long)dwg->header.section[0].address);
2175 LOG_TRACE (" Header Variables (end): %4u\n", (unsigned)dat->byte);
2176
2177 /*------------------------------------------------------------
2178 * Classes
2179 */
2180 SINCE (R_2004)
2181 {
2182 sec_id = SECTION_CLASSES;
2183 bit_chain_init_dat (&sec_dat[sec_id],
2184 (sizeof (Dwg_Class) * dwg->num_classes) + 32, dat);
2185 str_dat = hdl_dat = dat = &sec_dat[sec_id];
2186 }
2187 else sec_id = SECTION_CLASSES_R13;
2188 LOG_INFO ("\n=======> Classes: %4u (%d)\n", (unsigned)dat->byte,
2189 dwg->num_classes);
2190 if (dwg->num_classes > 5000)
2191 {
2192 LOG_ERROR ("Invalid dwg->num_classes %d", dwg->num_classes)
2193 dwg->num_classes = 0;
2194 error |= DWG_ERR_VALUEOUTOFBOUNDS | DWG_ERR_CLASSESNOTFOUND;
2195 }
2196 dwg->header.section[sec_id].number = 1;
2197 dwg->header.section[sec_id].address = dat->byte; // FIXME
2198 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN));
2199 pvzadr = dat->byte; // Size position
2200 bit_write_RL (dat, 0); // Size placeholder
2201
2202 for (j = 0; j < dwg->num_classes; j++)
2203 {
2204 Dwg_Class *klass;
2205 klass = &dwg->dwg_class[j];
2206 bit_write_BS (dat, klass->number);
2207 bit_write_BS (dat, klass->proxyflag);
2208 SINCE (R_2007) {
2209 bit_write_T (dat, klass->appname);
2210 bit_write_T (dat, klass->cppname);
2211 } else {
2212 bit_write_TV (dat, klass->appname);
2213 bit_write_TV (dat, klass->cppname);
2214 }
2215 SINCE (R_2007) // only when we have it. like not for 2004 => 2007
2216 // conversions
2217 {
2218 if (klass->dxfname_u)
2219 bit_write_TU (dat, klass->dxfname_u);
2220 else
2221 bit_write_T (dat, klass->dxfname);
2222 }
2223 else // we always have this one
2224 bit_write_TV (dat, klass->dxfname);
2225 bit_write_B (dat, klass->is_zombie);
2226 bit_write_BS (dat, klass->item_class_id);
2227 LOG_TRACE ("Class %d 0x%x %s\n"
2228 " %s \"%s\" %d 0x%x\n",
2229 klass->number, klass->proxyflag, klass->dxfname,
2230 klass->cppname, klass->appname, klass->is_zombie,
2231 klass->item_class_id)
2232
2233 SINCE (R_2007)
2234 {
2235 if (dat->from_version < R_2007 && !klass->dwg_version) {
2236 // defaults
2237 klass->dwg_version = (BITCODE_BL)dwg->header.dwg_version;
2238 klass->maint_version = (BITCODE_BL)dwg->header.maint_version;
2239 // TODO num_instances
2240 }
2241 bit_write_BL (dat, klass->num_instances);
2242 bit_write_BL (dat, klass->dwg_version);
2243 bit_write_BL (dat, klass->maint_version);
2244 bit_write_BL (dat, klass->unknown_1);
2245 bit_write_BL (dat, klass->unknown_2);
2246 LOG_TRACE (" %d %d\n", (int)klass->num_instances,
2247 (int)klass->dwg_version);
2248 }
2249 }
2250
2251 /* Write the size of the section at its beginning
2252 */
2253 assert (pvzadr);
2254 encode_patch_RLsize (dat, pvzadr);
2255 bit_write_CRC (dat, pvzadr, 0xC0C1);
2256 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_CLASS_END));
2257 dwg->header.section[SECTION_CLASSES_R13].size
2258 = dat->byte - dwg->header.section[SECTION_CLASSES_R13].address;
2259 LOG_TRACE (" Classes (end): %4u\n", (unsigned)dat->byte);
2260
2261 bit_write_RL (dat, 0x0DCA); // 0xDCA Unknown bitlong inter class and objects
2262 LOG_TRACE ("unknown: %04X [RL]\n", 0x0DCA);
2263
2264 /*------------------------------------------------------------
2265 * Objects
2266 */
2267
2268 SINCE (R_2004)
2269 {
2270 sec_id = SECTION_OBJECTS;
2271 bit_chain_alloc (&sec_dat[sec_id]);
2272 str_dat = hdl_dat = dat = &sec_dat[sec_id];
2273 bit_chain_set_version (dat, old_dat);
2274 }
2275 LOG_INFO ("\n=======> Objects: %4u\n", (unsigned)dat->byte);
2276 pvzadr = dat->byte;
2277
2278 /* Sort object-map by ascending handles
2279 */
2280 LOG_TRACE ("num_objects: %i\n", dwg->num_objects);
2281 LOG_TRACE ("num_object_refs: %i\n", dwg->num_object_refs);
2282 omap = (Object_Map *)calloc (dwg->num_objects, sizeof (Object_Map));
2283 if (!omap)
2284 {
2285 LOG_ERROR ("Out of memory");
2286 return DWG_ERR_OUTOFMEM;
2287 }
2288 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
2289 {
2290 LOG_HANDLE ("\nSorting objects...\n");
2291 for (i = 0; i < dwg->num_objects; i++)
2292 fprintf (OUTPUT, "Object(%3i): %4lX / idx: %u\n", i,
2293 dwg->object[i].handle.value, dwg->object[i].index);
2294 }
2295 // init unsorted
2296 for (i = 0; i < dwg->num_objects; i++)
2297 {
2298 omap[i].index = i; // i.e. dwg->object[j].index
2299 omap[i].handle = dwg->object[i].handle.value;
2300 }
2301 // insertion sort
2302 for (i = 0; i < dwg->num_objects; i++)
2303 {
2304 Object_Map tmap;
2305 j = i;
2306 tmap = omap[i];
2307 while (j > 0 && omap[j - 1].handle > tmap.handle)
2308 {
2309 omap[j] = omap[j - 1];
2310 j--;
2311 }
2312 omap[j] = tmap;
2313 }
2314 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
2315 {
2316 LOG_HANDLE ("\nSorted handles:\n");
2317 for (i = 0; i < dwg->num_objects; i++)
2318 fprintf (OUTPUT, "Handle(%3i): %4lX / idx: %u\n", i, omap[i].handle,
2319 omap[i].index);
2320 }
2321
2322 /* Write the sorted objects
2323 */
2324 for (i = 0; i < dwg->num_objects; i++)
2325 {
2326 Dwg_Object *obj;
2327 BITCODE_BL index = omap[i].index;
2328 unsigned long hdloff = omap[i].handle - (i ? omap[i - 1].handle : 0);
2329 int off = dat->byte - (i ? omap[i - 1].address : 0);
2330 unsigned long end_address;
2331 LOG_TRACE ("\n> Next object: " FORMAT_BL
2332 " Handleoff: %lX [UMC] Offset: %d [MC] @%lu\n"
2333 "==========================================\n",
2334 i, hdloff, off, dat->byte);
2335 omap[i].address = dat->byte;
2336 if (index > dwg->num_objects)
2337 {
2338 LOG_ERROR ("Invalid object map index " FORMAT_BL ", max " FORMAT_BL
2339 ". Skipping",
2340 index, dwg->num_objects)
2341 error |= DWG_ERR_VALUEOUTOFBOUNDS;
2342 continue;
2343 }
2344 obj = &dwg->object[index];
2345 // change the address to the linearly sorted one
2346 #ifndef NDEBUG
2347 PRE (R_2004)
2348 assert (dat->byte);
2349 #endif
2350 if (!obj->parent)
2351 obj->parent = dwg;
2352 error |= dwg_encode_add_object (obj, dat, dat->byte);
2353
2354 #ifndef NDEBUG
2355 // check if this object overwrote at address 0. but with r2004 it starts
2356 // fresh.
2357 if (dwg->header.version >= R_1_2 && dwg->header.version < R_2004)
2358 {
2359 if (dat->size < 6 || dat->chain[0] != 'A' || dat->chain[1] != 'C')
2360 {
2361 LOG_ERROR ("Encode overwrite pos 0, invalid DWG magic");
2362 return DWG_ERR_INVALIDDWG;
2363 }
2364 assert (dat->size > 6);
2365 assert (dat->chain[0] == 'A');
2366 assert (dat->chain[1] == 'C');
2367 }
2368 #endif
2369 end_address = omap[i].address + (unsigned long)obj->size; // from RL
2370 if (end_address > dat->size)
2371 {
2372 dat->size = end_address;
2373 bit_chain_alloc (dat);
2374 }
2375 }
2376
2377 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_HANDLE)
2378 {
2379 LOG_HANDLE ("\nSorted objects:\n");
2380 for (i = 0; i < dwg->num_objects; i++)
2381 LOG_HANDLE ("Object(%d): %lX / Address: %ld / Idx: %d\n", i,
2382 omap[i].handle, omap[i].address, omap[i].index);
2383 }
2384
2385 /* Unknown CRC between objects and object map
2386 */
2387 bit_write_RS (dat, 0);
2388 LOG_TRACE ("unknown crc?: %04X [RS]\n", 0);
2389
2390 /*------------------------------------------------------------
2391 * Object-map
2392 * split into chunks of max. 2030
2393 */
2394 LOG_INFO ("\n=======> Object Map: %4u\n", (unsigned)dat->byte);
2395 SINCE (R_2004)
2396 {
2397 sec_id = SECTION_HANDLES;
2398 bit_chain_init_dat (&sec_dat[sec_id], (8 * dwg->num_objects) + 32, dat);
2399 str_dat = hdl_dat = dat = &sec_dat[sec_id];
2400 }
2401 else
2402 {
2403 sec_id = SECTION_HANDLES_R13;
2404 dwg->header.section[sec_id].number = 2;
2405 dwg->header.section[sec_id].address = dat->byte;
2406 pvzadr = dat->byte; // Correct value of section size must be written later
2407 dat->byte += 2;
2408 }
2409
2410 last_offset = 0;
2411 last_handle = 0;
2412 for (i = 0; i < dwg->num_objects; i++)
2413 {
2414 BITCODE_BL index;
2415 BITCODE_UMC handleoff;
2416 BITCODE_MC offset;
2417
2418 index = omap[i].index;
2419 handleoff = omap[i].handle - last_handle;
2420 bit_write_UMC (dat, handleoff);
2421 LOG_HANDLE ("Handleoff(%3i): %4lX [UMC] (%4lX), ", index, handleoff,
2422 omap[i].handle)
2423 last_handle = omap[i].handle;
2424
2425 offset = omap[i].address - last_offset;
2426 bit_write_MC (dat, offset);
2427 last_offset = omap[i].address;
2428 LOG_HANDLE ("Offset: %8d [MC] @%lu\n", (int)offset, last_offset);
2429
2430 ckr_missing = 1;
2431 if (dat->byte - pvzadr > 2030) // 2029
2432 {
2433 ckr_missing = 0;
2434 sec_size = dat->byte - pvzadr;
2435 assert (pvzadr);
2436 // i.e. encode_patch_RS_LE_size
2437 dat->chain[pvzadr] = sec_size >> 8;
2438 dat->chain[pvzadr + 1] = sec_size & 0xFF;
2439 LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", sec_size, pvzadr);
2440 bit_write_CRC_LE (dat, pvzadr, 0xC0C1);
2441
2442 pvzadr = dat->byte;
2443 dat->byte += 2;
2444 last_offset = 0;
2445 last_handle = 0;
2446 }
2447 }
2448 // printf ("Obj size: %u\n", i);
2449 if (ckr_missing)
2450 {
2451 sec_size = dat->byte - pvzadr;
2452 #ifndef NDEBUG
2453 PRE (R_2004)
2454 assert (pvzadr);
2455 #endif
2456 if (pvzadr + 1 >= dat->size)
2457 bit_chain_alloc(dat);
2458 // i.e. encode_patch_RS_LE_size
2459 dat->chain[pvzadr] = sec_size >> 8;
2460 dat->chain[pvzadr + 1] = sec_size & 0xFF;
2461 LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", sec_size, pvzadr);
2462 bit_write_CRC_LE (dat, pvzadr, 0xC0C1);
2463 }
2464 #ifndef NDEBUG
2465 if (dwg->header.version >= R_1_2 && dwg->header.version < R_2004)
2466 {
2467 if (dat->size < 4 || dat->chain[0] != 'A' || dat->chain[1] != 'C')
2468 {
2469 LOG_ERROR ("Encode overwrite pos 0");
2470 return DWG_ERR_INVALIDDWG;
2471 }
2472 assert (dat->chain[0] == 'A');
2473 assert (dat->chain[1] == 'C');
2474 }
2475 PRE (R_2004)
2476 assert (dat->byte);
2477 #endif
2478 pvzadr = dat->byte;
2479 bit_write_RS_LE (dat, 2); // last section_size 2
2480 LOG_TRACE ("Handles page size: %u [RS_LE] @%lu\n", 2, pvzadr);
2481 bit_write_CRC_LE (dat, pvzadr, 0xC0C1);
2482
2483 /* Calculate and write the size of the object map
2484 */
2485 dwg->header.section[sec_id].size
2486 = dat->byte - dwg->header.section[sec_id].address;
2487 free (omap);
2488
2489 /*------------------------------------------------------------
2490 * Second header, section 3. R13-R2000 only.
2491 * But partially also since r2004. (TODO: under which name? AuxHeader?)
2492 */
2493 if (dwg->header.version >= R_13 && dwg->header.version < R_2004 // TODO
2494 && dwg->second_header.num_sections > 3)
2495 {
2496 struct _dwg_second_header *_obj = &dwg->second_header;
2497 Dwg_Object *obj = NULL;
2498 BITCODE_BL vcount;
2499
2500 assert (dat->byte);
2501 if (!_obj->address)
2502 _obj->address = dat->byte;
2503 dwg->header.section[SECTION_2NDHEADER_R13].number = 3;
2504 dwg->header.section[SECTION_2NDHEADER_R13].address = _obj->address;
2505 dwg->header.section[SECTION_2NDHEADER_R13].size = _obj->size;
2506 LOG_INFO ("\n=======> Second Header: %4u\n", (unsigned)dat->byte);
2507 bit_write_sentinel (dat,
2508 dwg_sentinel (DWG_SENTINEL_SECOND_HEADER_BEGIN));
2509
2510 pvzadr = dat->byte; // Keep the first address of the section to write its
2511 // size later
2512 LOG_TRACE ("pvzadr: %u\n", (unsigned)pvzadr);
2513 if (!_obj->size && !_obj->num_sections)
2514 {
2515 LOG_TRACE ("Use second_header defaults...\n");
2516 strcpy ((char *)&_obj->version[0],
2517 &version_codes[dwg->header.version][0]);
2518 memset (&_obj->version[7], 0, 4);
2519 _obj->version[11] = '\n';
2520 _obj->unknown_10 = 0x10;
2521 _obj->unknown_rc4[0] = 0x84;
2522 _obj->unknown_rc4[1] = 0x74;
2523 _obj->unknown_rc4[2] = 0x78;
2524 _obj->unknown_rc4[3] = 0x1;
2525 _obj->junk_r14_1 = 1957593121; //?
2526 _obj->junk_r14_2 = 2559919056; //?
2527 // TODO handlers defaults
2528 }
2529 // always recomputed, even with dwgrewrite
2530 if (dwg->header.version <= R_2000)
2531 {
2532 _obj->num_sections = dwg->header.num_sections;
2533 for (i = 0; i < _obj->num_sections; i++)
2534 {
2535 _obj->section[i].nr = dwg->header.section[i].number;
2536 _obj->section[i].address = dwg->header.section[i].address;
2537 _obj->section[i].size = dwg->header.section[i].size;
2538 }
2539 }
2540 FIELD_RL (size, 0);
2541 if (FIELD_VALUE (address) != (BITCODE_RL) (pvzadr - 16))
2542 {
2543 LOG_WARN ("second_header->address %u != %u", FIELD_VALUE (address),
2544 (unsigned)(pvzadr - 16));
2545 FIELD_VALUE (address) = pvzadr - 16;
2546 dwg->header.section[SECTION_2NDHEADER_R13].address = _obj->address;
2547 dwg->header.section[SECTION_2NDHEADER_R13].size = _obj->size;
2548 }
2549 FIELD_BL (address, 0);
2550
2551 // AC1012, AC1014 or AC1015. This is a char[11], zero padded.
2552 // with \n at 12.
2553 bit_write_TF (dat, (BITCODE_TF)_obj->version, 12);
2554 LOG_TRACE ("version: %s [TFF 12]\n", _obj->version)
2555
2556 for (i = 0; i < 4; i++)
2557 FIELD_B (null_b[i], 0);
2558 FIELD_RC (unknown_10, 0); // 0x10
2559 for (i = 0; i < 4; i++)
2560 FIELD_RC (unknown_rc4[i], 0);
2561
2562 UNTIL (R_2000)
2563 {
2564 FIELD_RC (num_sections, 0); // r14: 5, r2000: 6 (auxheader)
2565 for (i = 0; i < FIELD_VALUE (num_sections); i++)
2566 {
2567 FIELD_RC (section[i].nr, 0);
2568 FIELD_BL (section[i].address, 0);
2569 FIELD_BLd (section[i].size, 0);
2570 }
2571
2572 FIELD_BS (num_handlers, 0); // 14, resp. 16 in r14
2573 if (FIELD_VALUE (num_handlers) > 16)
2574 {
2575 LOG_ERROR ("Second header num_handlers > 16: %d\n",
2576 FIELD_VALUE (num_handlers));
2577 FIELD_VALUE (num_handlers) = 14;
2578 }
2579 for (i = 0; i < FIELD_VALUE (num_handlers); i++)
2580 {
2581 FIELD_RC (handlers[i].size, 0);
2582 FIELD_RC (handlers[i].nr, 0);
2583 FIELD_VECTOR (handlers[i].data, RC, handlers[i].size, 0);
2584 }
2585
2586 _obj->size = encode_patch_RLsize (dat, pvzadr);
2587 bit_write_CRC (dat, pvzadr, 0xC0C1);
2588
2589 VERSION (R_14)
2590 {
2591 FIELD_RL (junk_r14_1, 0);
2592 FIELD_RL (junk_r14_2, 0);
2593 }
2594 }
2595 bit_write_sentinel (dat, dwg_sentinel (DWG_SENTINEL_SECOND_HEADER_END));
2596 dwg->header.section[SECTION_2NDHEADER_R13].size
2597 = dat->byte - _obj->address;
2598 }
2599 else if (dwg->header.num_sections > SECTION_2NDHEADER_R13
2600 && dwg->header.version < R_2004) // TODO
2601 {
2602 dwg->header.section[SECTION_2NDHEADER_R13].number = 3;
2603 dwg->header.section[SECTION_2NDHEADER_R13].address = 0;
2604 dwg->header.section[SECTION_2NDHEADER_R13].size = 0;
2605 }
2606
2607 /*------------------------------------------------------------
2608 * MEASUREMENT/Template Section 4
2609 * In a DXF under header_vars
2610 */
2611 SINCE (R_2004)
2612 {
2613 sec_id = SECTION_TEMPLATE;
2614 bit_chain_init_dat (&sec_dat[sec_id], 16, dat);
2615 str_dat = hdl_dat = dat = &sec_dat[sec_id];
2616 }
2617 else sec_id = SECTION_MEASUREMENT_R13;
2618
2619 if (dwg->header.version >= R_2004 || (int)dwg->header.num_sections > sec_id)
2620 {
2621 LOG_INFO ("\n=======> MEASUREMENT: %4u\n", (unsigned)dat->byte);
2622 dwg->header.section[sec_id].number = 4;
2623 dwg->header.section[sec_id].address = dat->byte;
2624 dwg->header.section[sec_id].size = 4;
2625 // 0 - English, 1- Metric
2626 bit_write_RL_LE (dat, (BITCODE_RL)dwg->header_vars.MEASUREMENT ? 256 : 0);
2627 LOG_TRACE ("HEADER.MEASUREMENT: %d [RL_LE]\n",
2628 dwg->header_vars.MEASUREMENT);
2629 }
2630
2631 /* End of the file
2632 */
2633 dat->size = dat->byte;
2634 SINCE (R_2004)
2635 {
2636 Dwg_Section_Type type;
2637 Dwg_Object *obj = NULL;
2638 BITCODE_BL vcount, rcount3;
2639 size_t size;
2640 unsigned total_size = 0;
2641
2642 // write remaining section data
2643 for (type = SECTION_OBJFREESPACE; type < SECTION_SYSTEM_MAP; type++)
2644 {
2645 if (type != SECTION_OBJECTS && type != SECTION_PREVIEW)
2646 LOG_TRACE ("\n=== Section %s ===\n", dwg_section_name (dwg, type))
2647 switch (type)
2648 {
2649 case SECTION_HEADER: // ignore, already done
2650 case SECTION_AUXHEADER:
2651 case SECTION_CLASSES:
2652 case SECTION_HANDLES:
2653 case SECTION_TEMPLATE:
2654 case SECTION_PREVIEW:
2655 case SECTION_OBJECTS:
2656 case SECTION_UNKNOWN: // deferred
2657 case SECTION_INFO:
2658 case SECTION_SYSTEM_MAP:
2659 break;
2660 case SECTION_OBJFREESPACE:
2661 {
2662 Dwg_ObjFreeSpace *_obj = &dwg->objfreespace;
2663 bit_chain_alloc (&sec_dat[type]);
2664 str_dat = hdl_dat = dat = &sec_dat[type];
2665 bit_chain_set_version (dat, old_dat);
2666 #include "objfreespace.spec"
2667 LOG_TRACE ("-size: %lu\n", dat->byte)
2668 }
2669 break;
2670 case SECTION_REVHISTORY:
2671 {
2672 Dwg_RevHistory *_obj = &dwg->revhistory;
2673 bit_chain_alloc (&sec_dat[type]);
2674 str_dat = hdl_dat = dat = &sec_dat[type];
2675 bit_chain_set_version (dat, old_dat);
2676 #include "revhistory.spec"
2677 LOG_TRACE ("-size: %lu\n", dat->byte)
2678 }
2679 break;
2680 case SECTION_SUMMARYINFO:
2681 {
2682 Dwg_SummaryInfo *_obj = &dwg->summaryinfo;
2683 bit_chain_alloc (&sec_dat[type]);
2684 str_dat = hdl_dat = dat = &sec_dat[type];
2685 bit_chain_set_version (dat, old_dat);
2686 #include "summaryinfo.spec"
2687 LOG_TRACE ("-size: %lu\n", dat->byte)
2688 }
2689 break;
2690 case SECTION_APPINFO:
2691 {
2692 Dwg_AppInfo *_obj = &dwg->appinfo;
2693 bit_chain_alloc (&sec_dat[type]);
2694 str_dat = hdl_dat = dat = &sec_dat[type];
2695 bit_chain_set_version (dat, old_dat);
2696 #include "appinfo.spec"
2697 LOG_TRACE ("-size: %lu\n", dat->byte)
2698 }
2699 break;
2700 case SECTION_APPINFOHISTORY:
2701 {
2702 #if 0
2703 Dwg_AppInfoHistory *_obj = &dwg->appinfohistory;
2704 bit_chain_alloc (&sec_dat[type]);
2705 str_dat = hdl_dat = dat = &sec_dat[type];
2706 bit_chain_set_version (dat, old_dat);
2707 # include "appinfohistory.spec"
2708 LOG_TRACE ("-size: %lu\n", dat->byte)
2709 #endif
2710 }
2711 break;
2712 case SECTION_FILEDEPLIST:
2713 {
2714 Dwg_FileDepList *_obj = &dwg->filedeplist;
2715 bit_chain_alloc (&sec_dat[type]);
2716 str_dat = hdl_dat = dat = &sec_dat[type];
2717 bit_chain_set_version (dat, old_dat);
2718 #include "filedeplist.spec"
2719 LOG_TRACE ("-size: %lu\n", dat->byte)
2720 }
2721 break;
2722 case SECTION_SECURITY:
2723 {
2724 Dwg_Security *_obj = &dwg->security;
2725 bit_chain_alloc (&sec_dat[type]);
2726 str_dat = hdl_dat = dat = &sec_dat[type];
2727 bit_chain_set_version (dat, old_dat);
2728 #include "security.spec"
2729 LOG_TRACE ("-size: %lu\n", dat->byte)
2730 }
2731 break;
2732 case SECTION_SIGNATURE:
2733 {
2734 #if 0
2735 Dwg_Signature *_obj = &dwg->signature;
2736 bit_chain_alloc (&sec_dat[type]);
2737 str_dat = hdl_dat = dat = &sec_dat[type];
2738 bit_chain_set_version (dat, old_dat);
2739 {
2740 # include "signature.spec"
2741 }
2742 LOG_TRACE ("-size: %lu\n", dat->byte)
2743 #endif
2744 }
2745 break;
2746 case SECTION_ACDS:
2747 {
2748 #if 0
2749 Dwg_AcDs *_obj = &dwg->acds;
2750 bit_chain_alloc (&sec_dat[type]);
2751 str_dat = hdl_dat = dat = &sec_dat[type];
2752 bit_chain_set_version (dat, old_dat);
2753 {
2754 # include "acds.spec"
2755 }
2756 LOG_TRACE ("-size: %lu\n", dat->byte)
2757 #endif
2758 }
2759 break;
2760 case SECTION_VBAPROJECT: // nyi
2761 default:
2762 break;
2763 }
2764 }
2765 // and write system and data section maps.
2766 dat = old_dat;
2767
2768 /*-------------------------------------------------------------------------
2769 * Section map and info
2770 */
2771 // no gaps, so header->num_sections == r2004_header->numsections
2772 // get together all the section sizes, and set the addresses
2773 {
2774 int ssize;
2775 int si, info_id;
2776 unsigned address;
2777
2778 const Dwg_Section_Type section_map_order[] = {
2779 // R2004_Header
2780 SECTION_UNKNOWN, // the empty section 128-256
2781 SECTION_SECURITY, SECTION_FILEDEPLIST, SECTION_ACDS,
2782 SECTION_VBAPROJECT,
2783 SECTION_APPINFOHISTORY, //? at least before AppInfo
2784 SECTION_APPINFO, SECTION_PREVIEW,
2785 SECTION_SUMMARYINFO, // sometimes this is before Preview
2786 SECTION_REVHISTORY, SECTION_OBJECTS, SECTION_OBJFREESPACE,
2787 SECTION_TEMPLATE, SECTION_HANDLES, SECTION_CLASSES,
2788 SECTION_AUXHEADER, SECTION_HEADER, SECTION_SIGNATURE,
2789
2790 SECTION_INFO, SECTION_SYSTEM_MAP
2791 };
2792
2793 // not the order in the system map, but the order in the dat stream.
2794 const Dwg_Section_Type stream_order[]
2795 = { // R2004_Header
2796 SECTION_UNKNOWN, // the empty section 128-256
2797 SECTION_SUMMARYINFO, SECTION_PREVIEW, SECTION_VBAPROJECT,
2798 SECTION_APPINFO, SECTION_APPINFOHISTORY, SECTION_FILEDEPLIST,
2799 SECTION_ACDS, SECTION_REVHISTORY, SECTION_SECURITY,
2800 SECTION_OBJECTS, SECTION_OBJFREESPACE, SECTION_TEMPLATE,
2801 SECTION_HANDLES, SECTION_CLASSES, SECTION_AUXHEADER,
2802 SECTION_HEADER,
2803
2804 SECTION_SIGNATURE, //?
2805
2806 SECTION_INFO, SECTION_SYSTEM_MAP
2807 };
2808
2809 dwg->r2004_header.numsections = 0;
2810 dwg->r2004_header.numgaps = 0;
2811
2812 //sec_dat[SECTION_UNKNOWN].byte = 0;
2813 sec_dat[SECTION_INFO].byte = 10
2814 + (dwg->header.section_infohdr.num_desc
2815 * sizeof (Dwg_Section_Info));
2816 // only a guess, reserve at least one page
2817 sec_dat[SECTION_SYSTEM_MAP].byte = (4 * 20 * sizeof (Dwg_Section));
2818
2819 section_address = 0x100;
2820 // first all the data pages, than a number gap of 1, and last the two
2821 // system page maps, info and system_map the data_pages (system_map
2822 // sections) can include multiple pages of the same type.
2823 LOG_TRACE ("\n=== Section map and info page sizes ===\n");
2824 for (si = 0, info_id = 0, type = 0; type <= SECTION_SYSTEM_MAP;
2825 type++, i++)
2826 {
2827 if (sec_dat[type].byte)
2828 {
2829 const unsigned int max_decomp_size
2830 = section_max_decomp_size (dwg, type);
2831 const char *name = dwg_section_name (dwg, type);
2832 Dwg_Section_Info *info;
2833 if (sec_dat[type].bit)
2834 {
2835 LOG_WARN ("Unpadded section %d", type);
2836 sec_dat[type].byte++;
2837 }
2838 ssize = (int)sec_dat[type].byte;
2839 sec_dat[type].size = ssize;
2840 if (info_id >= (int)dwg->header.section_infohdr.num_desc)
2841 {
2842 dwg->header.section_infohdr.num_desc = info_id + 1;
2843 dwg->header.section_info
2844 = realloc (dwg->header.section_info,
2845 (info_id + 1) * sizeof (Dwg_Section));
2846 }
2847 info = &dwg->header.section_info[info_id];
2848 info->fixedtype = type;
2849 info->type = type;
2850 info->unknown = 1;
2851 if (name && si && type < SECTION_INFO) // not UNKNOWN and the last two
2852 strcpy (info->name, name);
2853 else
2854 memset (info->name, 0, 64);
2855 info->size = ssize;
2856 info->max_decomp_size = max_decomp_size;
2857 info->encrypted = section_encrypted (dwg, type);
2858 info->compressed = 1 + section_compressed (dwg, type);
2859 #ifndef HAVE_COMPRESS_R2004_SECTION
2860 info->compressed = 1;
2861 #endif
2862 // pre-calc num_sections for both
2863 if ((unsigned)ssize <= max_decomp_size)
2864 info->num_sections = 1;
2865 else
2866 {
2867 info->num_sections = (unsigned)ssize / max_decomp_size;
2868 if ((unsigned)ssize % max_decomp_size)
2869 info->num_sections++;
2870 }
2871 info->sections
2872 = calloc (info->num_sections, sizeof (Dwg_Section*));
2873 // enough sections?
2874 if (si + info->num_sections > dwg->header.num_sections)
2875 {
2876 Dwg_Section *oldsecs = dwg->header.section;
2877 dwg->header.num_sections = si + info->num_sections;
2878 dwg->header.section = realloc (dwg->header.section,
2879 dwg->header.num_sections
2880 * sizeof (Dwg_Section));
2881 if (dwg->header.section != oldsecs)
2882 // need to rebuild all info->sections
2883 section_info_rebuild (dwg, type);
2884 }
2885 {
2886 int ssi = 0;
2887 do
2888 {
2889 Dwg_Section *sec = &dwg->header.section[si];
2890 total_size += ssize;
2891 sec->number = si + 1; // index starting at 1
2892 sec->size = MIN (max_decomp_size, (unsigned)ssize);
2893 sec->decomp_data_size = sec->size;
2894 sec->type = type;
2895 sec->compression_type = info->compressed;
2896 info->sections[ssi] = sec;
2897 LOG_TRACE ("section[%d] %s[%d].sections[%d]: number=%d "
2898 "size=%d\n", si,
2899 dwg_section_name (dwg, type), info_id, ssi,
2900 sec->number, (int)sec->size);
2901 ssize -= max_decomp_size;
2902 ssi++; // info->sections index
2903 si++; // section index
2904 }
2905 while (ssize > (int)max_decomp_size); // keep same type
2906 }
2907 info_id++;
2908 }
2909 else
2910 LOG_TRACE ("section_info %s is empty, skipped. size=0\n",
2911 dwg_section_name (dwg, type));
2912 }
2913 dwg->r2004_header.numsections = si;
2914 // section_info [27] and section_map [28] as two last already added.
2915 if ((unsigned)si > dwg->header.num_sections) // needed?
2916 {
2917 Dwg_Section *oldsecs = dwg->header.section;
2918 dwg->header.num_sections = si;
2919 dwg->header.section = realloc (dwg->header.section, si * sizeof (Dwg_Section));
2920 if (dwg->header.section != oldsecs)
2921 section_info_rebuild (dwg, SECTION_SYSTEM_MAP);
2922 }
2923 dwg->r2004_header.section_info_id = dwg->r2004_header.numsections + 1; // a gap of 3
2924 dwg->r2004_header.section_map_id = dwg->r2004_header.numsections + 2;
2925 dwg->r2004_header.section_array_size = dwg->r2004_header.numsections + 2;
2926 dwg->r2004_header.last_section_id = dwg->r2004_header.section_map_id;
2927 dwg->header.section[si - 2].number = dwg->r2004_header.section_info_id;
2928 dwg->header.section[si - 1].number = dwg->r2004_header.section_map_id;
2929
2930 LOG_TRACE ("\n=== Section Info %d in map order ===\n",
2931 dwg->r2004_header.section_info_id);
2932 // write into sec_dat[type] first, then compress
2933 sec_id = SECTION_INFO;
2934 sec_dat[sec_id].size = sec_dat[sec_id].byte;
2935 bit_chain_alloc (&sec_dat[sec_id]);
2936 dat = &sec_dat[sec_id];
2937 bit_chain_set_version (dat, old_dat);
2938 bit_set_position (dat, 0); // so far we faked the content. now write it
2939
2940 {
2941 Dwg_Section_InfoHdr *_obj = &dwg->header.section_infohdr;
2942 Dwg_Section *sec = &dwg->header.section[si - 2];
2943 Dwg_Section_Info *info = find_section_info_type (dwg, sec_id);
2944 // index starting at 1
2945 sec->number = dwg->r2004_header.section_info_id;
2946 sec->size = MIN (0x7400, sec->size);
2947 sec->decomp_data_size = sec->size;
2948 sec->type = type;
2949 if (info)
2950 {
2951 sec->compression_type = info->compressed;
2952 // very unlikely, more than 1 page
2953 info->sections[0] = sec;
2954 }
2955 if (_obj->compressed == 2 && sec->size <= MIN_COMPRESSED_SECTION)
2956 _obj->compressed = 1;
2957 #ifndef HAVE_COMPRESS_R2004_SECTION
2958 _obj->compressed = 1;
2959 #endif
2960 LOG_HANDLE ("InfoHdr @%lu.0\n", dat->byte);
2961 FIELD_RL (num_desc, 0);
2962 FIELD_RL (compressed, 0);
2963 FIELD_RL (max_size, 0);
2964 FIELD_RL (encrypted, 0);
2965 FIELD_RL (num_desc2, 0);
2966 }
2967 for (i = 0; i < ARRAY_SIZE (section_map_order); i++)
2968 {
2969 Dwg_Section_Info *_obj;
2970 type = section_map_order[i];
2971 _obj = find_section_info_type (dwg, type);
2972 if (_obj)
2973 {
2974 assert (type == _obj->fixedtype);
2975 LOG_TRACE ("\nSection_Info %s [%d]\n",
2976 dwg_section_name (dwg, type), i);
2977 FIELD_RLLu (size, 0);
2978 FIELD_RL (num_sections, 0);
2979 FIELD_RL (max_decomp_size, 0);
2980 FIELD_RL (unknown, 0);
2981 FIELD_RL (compressed, 0);
2982 FIELD_RL (type, 0);
2983 FIELD_RL (encrypted, 0);
2984 bit_write_TF (dat, (unsigned char *)_obj->name, 64);
2985 LOG_TRACE ("name: %s\n", *_obj->name ? _obj->name : "");
2986 }
2987 }
2988
2989 LOG_TRACE ("\n=== Section System Map %d in map order ===\n",
2990 dwg->r2004_header.section_map_id);
2991 sec_id = type = SECTION_SYSTEM_MAP;
2992 {
2993 //Dwg_Section_InfoHdr *_obj = &dwg->header.section_infohdr;
2994 Dwg_Section *sec = &dwg->header.section[si - 1];
2995 Dwg_Section_Info *info = find_section_info_type (dwg, type);
2996 if (!info || !info->sections)
2997 {
2998 LOG_ERROR ("SECTION_SYSTEM_MAP not found");
2999 return DWG_ERR_SECTIONNOTFOUND;
3000 }
3001
3002 sec_dat[sec_id].size = sec_dat[sec_id].byte;
3003 bit_chain_alloc (&sec_dat[sec_id]);
3004 str_dat = hdl_dat = dat = &sec_dat[sec_id];
3005 bit_chain_set_version (dat, old_dat);
3006 bit_set_position (dat, 0); // so far we faked the content. now write it
3007
3008 // index starting at 1
3009 sec->number = dwg->r2004_header.section_map_id;
3010 sec->size = MIN (0x7400, sec->size);
3011 sec->decomp_data_size = sec->size;
3012 sec->type = type;
3013 sec->compression_type = info->compressed;
3014 // very unlikely, more than 1 page
3015 info->sections[0] = sec;
3016 }
3017
3018 address = 0x100;
3019 for (i = 0; i < dwg->header.num_sections; i++)
3020 {
3021 Dwg_Section *_obj = &dwg->header.section[i];
3022
3023 FIELD_RL (number, 0);
3024 FIELD_RL (size, 0);
3025 _obj->address = address;
3026 FIELD_RLL (address, 0);
3027 address += _obj->size;
3028 if (_obj->number < 0) // gap. unused. we deleted all gaps
3029 {
3030 FIELD_RL (parent, 0);
3031 FIELD_RL (left, 0);
3032 FIELD_RL (right, 0);
3033 FIELD_RL (x00, 0);
3034 }
3035 }
3036 dwg->r2004_header.decomp_data_size = dat->byte; // system_map_size
3037 LOG_TRACE ("-size: %lu\n", dat->byte);
3038
3039 dat = old_dat;
3040 #ifndef NDEBUG
3041 if (dwg->header.version >= R_1_2)
3042 {
3043 if (dat->size < 4 || dat->chain[0] != 'A' || dat->chain[1] != 'C')
3044 {
3045 LOG_ERROR ("Encode overwrite pos 0");
3046 return DWG_ERR_INVALIDDWG;
3047 }
3048 assert (dat->chain[0] == 'A');
3049 assert (dat->chain[1] == 'C');
3050 assert (dat->byte <= 0x100);
3051 }
3052 #endif
3053
3054 // now write all the sections in the stream order
3055 LOG_TRACE ("\n=== Write sections in stream order ===\n");
3056 size = total_size
3057 + (8 * ((dwg->r2004_header.numsections + 2) * 24)); // no gaps
3058 dat->byte = section_address;
3059 if (dat->byte + size >= dat->size)
3060 {
3061 dat->size = dat->byte + size;
3062 bit_chain_alloc (dat);
3063 }
3064 LOG_HANDLE ("@%lu.0\n", dat->byte);
3065 for (i = 0; i < ARRAY_SIZE (stream_order); i++)
3066 {
3067 Dwg_Section_Info *info;
3068 type = stream_order[i];
3069 info = find_section_info_type (dwg, type);
3070 if (info)
3071 {
3072 LOG_TRACE ("Write %s pages @%lu (%u/%lu)\n",
3073 dwg_section_name (dwg, type), dat->byte,
3074 info->num_sections, sec_dat[type].size);
3075 for (unsigned k = 0; k < info->num_sections; k++)
3076 {
3077 Dwg_Section *sec = info->sections[k];
3078 if (!sec)
3079 {
3080 LOG_ERROR ("empty info->sections[%u]", k);
3081 continue;
3082 }
3083 if (!sec_dat[type].chain)
3084 {
3085 LOG_ERROR ("empty %s.chain", dwg_section_name (dwg, type));
3086 continue;
3087 }
3088 #ifndef NDEBUG
3089 if (info->fixedtype < SECTION_INFO)
3090 assert (info->fixedtype == sec->type);
3091 #endif
3092 if (info->fixedtype == SECTION_SUMMARYINFO)
3093 dwg->header.summaryinfo_address = dat->byte;
3094 else if (info->fixedtype == SECTION_PREVIEW)
3095 dwg->header.thumbnail_address = dat->byte;
3096 else if (info->fixedtype == SECTION_VBAPROJECT)
3097 dwg->header.vbaproj_address = dat->byte;
3098 else if (info->fixedtype == SECTION_SYSTEM_MAP)
3099 {
3100 dwg->r2004_header.section_map_address = dat->byte - 0x100;
3101 dwg->r2004_header.last_section_address = dat->byte + sec->size - 0x100;
3102 dwg->r2004_header.second_header_address = 0; // TODO
3103 }
3104 sec->address = dat->byte;
3105
3106 if (info->encrypted)
3107 {
3108 BITCODE_RC *decr = calloc (sec->size, 1);
3109 LOG_HANDLE ("Encrypt %s (%u/%d)\n", info->name, k,
3110 sec->size);
3111 decrypt_R2004_header (decr, sec_dat[type].chain,
3112 sec->size);
3113 free (sec_dat[type].chain);
3114 sec_dat[type].chain = decr;
3115 }
3116 assert (sec->size <= MIN_COMPRESSED_SECTION ? info->compressed == 1 : 1);
3117 if (info->compressed == 2)
3118 {
3119 LOG_HANDLE ("Compress %s (%u/%d)\n", info->name, k,
3120 sec->size);
3121 compress_R2004_section (dat, sec_dat[type].chain,
3122 sec->size, &sec->comp_data_size);
3123 LOG_TRACE ("sec->comp_data_size: " FORMAT_RL "\n", sec->comp_data_size);
3124 }
3125 else
3126 {
3127 LOG_HANDLE ("Copy uncompressed %s (%u/%d)\n", info->name,
3128 k, sec->size);
3129 copy_R2004_section (dat, sec_dat[type].chain, sec->size,
3130 &sec->comp_data_size);
3131 }
3132 }
3133 bit_chain_free (&sec_dat[type]);
3134 }
3135 }
3136 }
3137
3138 {
3139 Dwg_R2004_Header *_obj = &dwg->r2004_header;
3140 Bit_Chain file_dat = { NULL, sizeof (Dwg_R2004_Header), 0UL, 0, 0, 0, 0, NULL };
3141 Bit_Chain *orig_dat = dat;
3142 /* "AcFssFcAJMB" encrypted: 6840F8F7922AB5EF18DD0BF1 */
3143 const unsigned char enc_file_ID_string[]
3144 = { '\x68', '\x40', '\xF8', '\xF7', '\x92', '\x2A',
3145 '\xB5', '\xEF', '\x18', '\xDD', '\x0B', '\xF1' };
3146 uint32_t checksum;
3147
3148 file_dat.chain = calloc (1, sizeof (Dwg_R2004_Header));
3149 dat = &file_dat;
3150 LOG_TRACE ("\nSection R2004_Header @0x100\n");
3151
3152 checksum = _obj->crc32;
3153 LOG_HANDLE ("old crc32: 0x%x\n", _obj->crc32);
3154 _obj->crc32 = 0;
3155 // recalc the CRC32, without the padding, but the crc32 as 0
3156 _obj->crc32
3157 = bit_calc_CRC32 (0, (unsigned char *)&dwg->r2004_header, 0x6c);
3158 LOG_HANDLE ("calc crc32: 0x%x\n", _obj->crc32);
3159
3160 // clang-format off
3161 #include "r2004_file_header.spec"
3162 // clang-format on
3163
3164 // go back and encrypt it
3165 dat = orig_dat;
3166 decrypt_R2004_header (&dat->chain[0x80], file_dat.chain,
3167 sizeof (Dwg_R2004_Header));
3168 bit_chain_free (&file_dat);
3169 LOG_HANDLE ("encrypted R2004_Header:\n");
3170 LOG_TF (HANDLE, &dat->chain[0x80], (int)sizeof (Dwg_R2004_Header));
3171 if (memcmp (&dat->chain[0x80], enc_file_ID_string,
3172 sizeof (enc_file_ID_string)))
3173 {
3174 LOG_ERROR ("r2004_file_header encryption error");
3175 return error | DWG_ERR_INVALIDDWG;
3176 }
3177 } // R2004_Header
3178 } // R_2004
3179
3180 assert (!dat->bit);
3181 dat->size = dat->byte;
3182 LOG_INFO ("\nFinal DWG size: %u\n", (unsigned)dat->size);
3183
3184 UNTIL (R_2000)
3185 {
3186 /* Patch section addresses
3187 */
3188 assert (section_address);
3189 dat->byte = section_address;
3190 dat->bit = 0;
3191 LOG_INFO ("\n=======> section addresses: %4u\n", (unsigned)dat->byte);
3192 for (j = 0; j < dwg->header.num_sections; j++)
3193 {
3194 LOG_TRACE ("section[%u].number: %4d [RC] %s\n", j,
3195 (int)dwg->header.section[j].number,
3196 j < 6 ? dwg_section_name (dwg, j) : "");
3197 LOG_TRACE ("section[%u].offset: %4u [RL]\n", j,
3198 (unsigned)dwg->header.section[j].address);
3199 LOG_TRACE ("section[%u].size: %4u [RL]\n", j,
3200 (int)dwg->header.section[j].size);
3201 if ((unsigned long)dwg->header.section[j].address
3202 + dwg->header.section[j].size
3203 > dat->size)
3204 {
3205 if (is_section_r13_critical (j))
3206 {
3207 LOG_ERROR ("section[%u] %s address or size overflow", j,
3208 j < 6 ? dwg_section_name (dwg, j) : "");
3209 return DWG_ERR_INVALIDDWG;
3210 }
3211 else
3212 {
3213 LOG_WARN ("section[%u] %s address or size overflow, skipped",
3214 j, j < 6 ? dwg_section_name (dwg, j) : "");
3215 dwg->header.section[j].address = 0;
3216 dwg->header.section[j].size = 0;
3217 }
3218 }
3219 bit_write_RC (dat, dwg->header.section[j].number);
3220 bit_write_RL (dat, dwg->header.section[j].address);
3221 bit_write_RL (dat, dwg->header.section[j].size);
3222 }
3223
3224 /* Write CRC's
3225 */
3226 bit_write_CRC (dat, 0, 0);
3227 dat->byte -= 2;
3228 ckr = bit_read_CRC (dat);
3229 dat->byte -= 2;
3230 // FIXME: r13-2000 only
3231 switch (dwg->header.num_sections)
3232 {
3233 case 3:
3234 ckr ^= 0xA598;
3235 break;
3236 case 4:
3237 ckr ^= 0x8101;
3238 break;
3239 case 5:
3240 ckr ^= 0x3CC4;
3241 break;
3242 case 6:
3243 ckr ^= 0x8461;
3244 break;
3245 default:
3246 break;
3247 }
3248 bit_write_RS (dat, ckr);
3249 LOG_TRACE ("crc: %04X (from 0)\n", ckr);
3250 }
3251
3252 return 0;
3253 }
3254 AFL_GCC_POP
3255
encode_preR13(Dwg_Data * restrict dwg,Bit_Chain * restrict dat)3256 static int encode_preR13 (Dwg_Data * restrict dwg, Bit_Chain * restrict dat)
3257 {
3258 return DWG_ERR_NOTYETSUPPORTED;
3259 }
3260
3261 #include "dwg.spec"
3262
3263 // expand aliases: name => CLASSES.dxfname
3264 static const char *
dxf_encode_alias(char * restrict name)3265 dxf_encode_alias (char *restrict name)
3266 {
3267 if (strEQc (name, "DICTIONARYWDFLT"))
3268 return "ACDBDICTIONARYWDFLT";
3269 else if (strEQc (name, "SECTIONVIEWSTYLE"))
3270 return "ACDBSECTIONVIEWSTYLE";
3271 else if (strEQc (name, "PLACEHOLDER"))
3272 return "ACDBPLACEHOLDER";
3273 else if (strEQc (name, "DETAILVIEWSTYLE"))
3274 return "ACDBDETAILVIEWSTYLE";
3275 else if (strEQc (name, "ASSOCPERSSUBENTMANAGER"))
3276 return "ACDBASSOCPERSSUBENTMANAGER";
3277 else if (strEQc (name, "EVALUATION_GRAPH"))
3278 return "ACAD_EVALUATION_GRAPH";
3279 else if (strEQc (name, "ASSOCACTION"))
3280 return "ACDBASSOCACTION";
3281 else if (strEQc (name, "ASSOCALIGNEDDIMACTIONBODY"))
3282 return "ACDBASSOCALIGNEDDIMACTIONBODY";
3283 else if (strEQc (name, "ASSOCOSNAPPOINTREFACTIONPARAM"))
3284 return "ACDBASSOCOSNAPPOINTREFACTIONPARAM";
3285 else if (strEQc (name, "ASSOCVERTEXACTIONPARAM"))
3286 return "ACDBASSOCVERTEXACTIONPARAM";
3287 else if (strEQc (name, "ASSOCGEOMDEPENDENCY"))
3288 return "ACDBASSOCGEOMDEPENDENCY";
3289 else if (strEQc (name, "ASSOCDEPENDENCY"))
3290 return "ACDBASSOCDEPENDENCY";
3291 else if (strEQc (name, "TABLE"))
3292 return "ACAD_TABLE";
3293 else
3294 return NULL;
3295 }
3296
3297 Dwg_Class *
dwg_encode_get_class(Dwg_Data * dwg,Dwg_Object * obj)3298 dwg_encode_get_class (Dwg_Data *dwg, Dwg_Object *obj)
3299 {
3300 int i;
3301 Dwg_Class *klass = NULL;
3302 if (!dwg || !dwg->dwg_class)
3303 return NULL;
3304 // indxf has a different class order
3305 if (obj->dxfname) // search class by name, not offset
3306 {
3307 int invalid_klass = 0;
3308 for (i = 0; i < dwg->num_classes; i++)
3309 {
3310 klass = &dwg->dwg_class[i];
3311 if (!klass->dxfname)
3312 {
3313 invalid_klass++;
3314 continue;
3315 }
3316 if (strEQ (obj->dxfname, klass->dxfname))
3317 {
3318 obj->type = 500 + i;
3319 break;
3320 }
3321 else
3322 {
3323 // alias DICTIONARYWDFLT => ACDBDICTIONARYWDFLT
3324 const char *alias = dxf_encode_alias (obj->dxfname);
3325 if (alias && klass->dxfname && strEQ (alias, klass->dxfname))
3326 {
3327 // a static string, which cannot be free'd. important for
3328 // indxf
3329 if (dwg->opts & DWG_OPTS_IN)
3330 obj->dxfname = strdup ((char *)alias);
3331 else
3332 obj->dxfname = (char *)alias;
3333 obj->type = 500 + i;
3334 break;
3335 }
3336 klass = NULL; // inefficient
3337
3338 if (invalid_klass > 2 && !(dwg->opts & DWG_OPTS_IN))
3339 goto search_by_index;
3340 }
3341 }
3342 }
3343 else // search by index
3344 {
3345 search_by_index:
3346 i = obj->type - 500;
3347 if (i < 0 || i >= (int)dwg->num_classes)
3348 {
3349 LOG_WARN ("Invalid object type %d, only %u classes", obj->type,
3350 dwg->num_classes);
3351 return NULL;
3352 }
3353
3354 klass = &dwg->dwg_class[i];
3355 if (!klass->dxfname)
3356 return NULL;
3357 obj->dxfname = klass->dxfname;
3358 }
3359 return klass;
3360 }
3361
3362 /** dwg_encode_variable_type
3363 * Encode object by class name, not type. if type > 500.
3364 * Returns 0 on success, else some Dwg_Error.
3365 */
3366 static int
dwg_encode_variable_type(Dwg_Data * restrict dwg,Bit_Chain * restrict dat,Dwg_Object * restrict obj)3367 dwg_encode_variable_type (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
3368 Dwg_Object *restrict obj)
3369 {
3370 //int error = 0;
3371 int is_entity;
3372 Dwg_Class *klass = dwg_encode_get_class (dwg, obj);
3373
3374 if (!klass)
3375 return DWG_ERR_INVALIDTYPE;
3376 is_entity = dwg_class_is_entity (klass);
3377 // check if it really was an entity
3378 if ((is_entity && obj->supertype == DWG_SUPERTYPE_OBJECT)
3379 || (!is_entity && obj->supertype == DWG_SUPERTYPE_ENTITY))
3380 {
3381 if (is_dwg_object (obj->name))
3382 {
3383 if (is_entity)
3384 {
3385 LOG_INFO ("Fixup Class %s item_class_id to %s for %s\n",
3386 klass->dxfname, "OBJECT", obj->name);
3387 klass->item_class_id = 0x1f2;
3388 if (!klass->dxfname || strNE (klass->dxfname, obj->dxfname))
3389 {
3390 free (klass->dxfname);
3391 klass->dxfname = strdup (obj->dxfname);
3392 }
3393 is_entity = 0;
3394 }
3395 else
3396 {
3397 LOG_INFO ("Fixup %s.supertype to %s\n", obj->name, "OBJECT");
3398 obj->supertype = DWG_SUPERTYPE_OBJECT;
3399 }
3400 }
3401 else if (is_dwg_entity (obj->name))
3402 {
3403 if (!is_entity)
3404 {
3405 LOG_INFO ("Fixup Class %s item_class_id to %s for %s\n",
3406 klass->dxfname, "ENTITY", obj->name);
3407 klass->item_class_id = 0x1f3;
3408 if (!klass->dxfname || strNE (klass->dxfname, obj->dxfname))
3409 {
3410 free (klass->dxfname);
3411 klass->dxfname = strdup (obj->dxfname);
3412 }
3413 is_entity = 1;
3414 }
3415 else
3416 {
3417 LOG_INFO ("Fixup %s.supertype to %s", obj->name, "ENTITY");
3418 obj->supertype = DWG_SUPERTYPE_ENTITY;
3419 }
3420 }
3421 else
3422 {
3423 LOG_ERROR ("Illegal Class %s is_%s item_class_id for %s",
3424 klass->dxfname, is_entity ? "entity" : "object",
3425 obj->name);
3426 return DWG_ERR_INVALIDTYPE;
3427 }
3428 }
3429
3430 if (dwg->opts & DWG_OPTS_IN) // DXF or JSON import
3431 {
3432 unsigned long pos = bit_position (dat);
3433
3434 /* Should not be triggered. Only when undef ENCODE_UNKNOWN_AS_DUMMY */
3435 if (is_type_unstable (obj->fixedtype) &&
3436 (obj->fixedtype == DWG_TYPE_WIPEOUT ||
3437 obj->fixedtype == DWG_TYPE_TABLEGEOMETRY))
3438 {
3439 LOG_WARN ("Skip broken %s", obj->name); // acad crashes still
3440 obj->type = is_entity ? DWG_TYPE_UNKNOWN_ENT : DWG_TYPE_PLACEHOLDER;
3441 klass->dxfname = strdup (is_entity ? "UNKNOWN_ENT" : "UNKNOWN_OBJ");
3442 }
3443 dat->byte = obj->address;
3444 dat->bit = 0;
3445 LOG_TRACE ("fixup Type: %d [BS] @%lu\n", obj->type, obj->address);
3446 bit_write_BS (dat, obj->type); // fixup wrong type
3447 bit_set_position (dat, pos);
3448 }
3449
3450 // clang-format off
3451 #include "classes.inc"
3452 // clang-format on
3453
3454 LOG_WARN ("Unknown Class %s %d %s (0x%x%s)", is_entity ? "entity" : "object",
3455 klass->number, klass->dxfname, klass->proxyflag,
3456 klass->is_zombie ? "is_zombie" : "")
3457
3458 #undef WARN_UNHANDLED_CLASS
3459 #undef WARN_UNSTABLE_CLASS
3460
3461 return DWG_ERR_UNHANDLEDCLASS;
3462 }
3463
3464 int
dwg_encode_add_object(Dwg_Object * restrict obj,Bit_Chain * restrict dat,unsigned long address)3465 dwg_encode_add_object (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
3466 unsigned long address)
3467 {
3468 int error = 0;
3469 //unsigned long oldpos;
3470 unsigned long end_address = address + obj->size;
3471 Dwg_Data *dwg = obj->parent;
3472
3473 //oldpos = bit_position (dat);
3474 PRE (R_2004)
3475 {
3476 if (!address)
3477 return DWG_ERR_INVALIDDWG;
3478 assert (address);
3479 }
3480 dat->byte = address;
3481 dat->bit = 0;
3482
3483 LOG_INFO ("Object number: %lu", (unsigned long)obj->index);
3484 if (obj->size > 0x100000)
3485 {
3486 LOG_ERROR ("Object size %u overflow", obj->size);
3487 return DWG_ERR_VALUEOUTOFBOUNDS;
3488 }
3489 while (dat->byte + obj->size >= dat->size)
3490 bit_chain_alloc (dat);
3491
3492 // First write an aproximate size here.
3493 // Then calculate size from the fields. Either <0x7fff or more.
3494 // Patch it afterwards and check old<>new size if enough space allocated.
3495 bit_write_MS (dat, obj->size);
3496 obj->address = dat->byte;
3497 PRE (R_2010)
3498 {
3499 bit_write_BS (dat, obj->type);
3500 LOG_INFO (", Size: %d [MS], Type: %d [BS], Address: %lu\n", obj->size, obj->type, obj->address)
3501 }
3502 LATER_VERSIONS
3503 {
3504 if (!obj->handlestream_size && obj->bitsize)
3505 obj->handlestream_size = obj->size * 8 - obj->bitsize;
3506 bit_write_UMC (dat, obj->handlestream_size);
3507 obj->address = dat->byte;
3508 bit_write_BOT (dat, obj->type);
3509 LOG_INFO (", Size: %d [MS], Hdlsize: %lu [UMC], Type: %d [BOT], Address: %lu\n",
3510 obj->size, (unsigned long)obj->handlestream_size, obj->type, obj->address)
3511 }
3512
3513 /* Write the specific type to dat */
3514 switch (obj->type)
3515 {
3516 case DWG_TYPE_TEXT:
3517 error = dwg_encode_TEXT (dat, obj);
3518 break;
3519 case DWG_TYPE_ATTRIB:
3520 error = dwg_encode_ATTRIB (dat, obj);
3521 break;
3522 case DWG_TYPE_ATTDEF:
3523 error = dwg_encode_ATTDEF (dat, obj);
3524 break;
3525 case DWG_TYPE_BLOCK:
3526 error = dwg_encode_BLOCK (dat, obj);
3527 break;
3528 case DWG_TYPE_ENDBLK:
3529 error = dwg_encode_ENDBLK (dat, obj);
3530 break;
3531 case DWG_TYPE_SEQEND:
3532 error = dwg_encode_SEQEND (dat, obj);
3533 break;
3534 case DWG_TYPE_INSERT:
3535 error = dwg_encode_INSERT (dat, obj);
3536 break;
3537 case DWG_TYPE_MINSERT:
3538 error = dwg_encode_MINSERT (dat, obj);
3539 break;
3540 case DWG_TYPE_VERTEX_2D:
3541 error = dwg_encode_VERTEX_2D (dat, obj);
3542 break;
3543 case DWG_TYPE_VERTEX_3D:
3544 error = dwg_encode_VERTEX_3D (dat, obj);
3545 break;
3546 case DWG_TYPE_VERTEX_MESH:
3547 error = dwg_encode_VERTEX_MESH (dat, obj);
3548 break;
3549 case DWG_TYPE_VERTEX_PFACE:
3550 error = dwg_encode_VERTEX_PFACE (dat, obj);
3551 break;
3552 case DWG_TYPE_VERTEX_PFACE_FACE:
3553 error = dwg_encode_VERTEX_PFACE_FACE (dat, obj);
3554 break;
3555 case DWG_TYPE_POLYLINE_2D:
3556 error = dwg_encode_POLYLINE_2D (dat, obj);
3557 break;
3558 case DWG_TYPE_POLYLINE_3D:
3559 error = dwg_encode_POLYLINE_3D (dat, obj);
3560 break;
3561 case DWG_TYPE_ARC:
3562 error = dwg_encode_ARC (dat, obj);
3563 break;
3564 case DWG_TYPE_CIRCLE:
3565 error = dwg_encode_CIRCLE (dat, obj);
3566 break;
3567 case DWG_TYPE_LINE:
3568 error = dwg_encode_LINE (dat, obj);
3569 break;
3570 case DWG_TYPE_DIMENSION_ORDINATE:
3571 error = dwg_encode_DIMENSION_ORDINATE (dat, obj);
3572 break;
3573 case DWG_TYPE_DIMENSION_LINEAR:
3574 error = dwg_encode_DIMENSION_LINEAR (dat, obj);
3575 break;
3576 case DWG_TYPE_DIMENSION_ALIGNED:
3577 error = dwg_encode_DIMENSION_ALIGNED (dat, obj);
3578 break;
3579 case DWG_TYPE_DIMENSION_ANG3PT:
3580 error = dwg_encode_DIMENSION_ANG3PT (dat, obj);
3581 break;
3582 case DWG_TYPE_DIMENSION_ANG2LN:
3583 error = dwg_encode_DIMENSION_ANG2LN (dat, obj);
3584 break;
3585 case DWG_TYPE_DIMENSION_RADIUS:
3586 error = dwg_encode_DIMENSION_RADIUS (dat, obj);
3587 break;
3588 case DWG_TYPE_DIMENSION_DIAMETER:
3589 error = dwg_encode_DIMENSION_DIAMETER (dat, obj);
3590 break;
3591 case DWG_TYPE_POINT:
3592 error = dwg_encode_POINT (dat, obj);
3593 break;
3594 case DWG_TYPE__3DFACE:
3595 error = dwg_encode__3DFACE (dat, obj);
3596 break;
3597 case DWG_TYPE_POLYLINE_PFACE:
3598 error = dwg_encode_POLYLINE_PFACE (dat, obj);
3599 break;
3600 case DWG_TYPE_POLYLINE_MESH:
3601 error = dwg_encode_POLYLINE_MESH (dat, obj);
3602 break;
3603 case DWG_TYPE_SOLID:
3604 error = dwg_encode_SOLID (dat, obj);
3605 break;
3606 case DWG_TYPE_TRACE:
3607 error = dwg_encode_TRACE (dat, obj);
3608 break;
3609 case DWG_TYPE_SHAPE:
3610 error = dwg_encode_SHAPE (dat, obj);
3611 break;
3612 case DWG_TYPE_VIEWPORT:
3613 error = dwg_encode_VIEWPORT (dat, obj);
3614 break;
3615 case DWG_TYPE_ELLIPSE:
3616 error = dwg_encode_ELLIPSE (dat, obj);
3617 break;
3618 case DWG_TYPE_SPLINE:
3619 error = dwg_encode_SPLINE (dat, obj);
3620 break;
3621 case DWG_TYPE_REGION:
3622 error = dwg_encode_REGION (dat, obj);
3623 break;
3624 case DWG_TYPE__3DSOLID:
3625 error = dwg_encode__3DSOLID (dat, obj);
3626 break;
3627 case DWG_TYPE_BODY:
3628 error = dwg_encode_BODY (dat, obj);
3629 break;
3630 case DWG_TYPE_RAY:
3631 error = dwg_encode_RAY (dat, obj);
3632 break;
3633 case DWG_TYPE_XLINE:
3634 error = dwg_encode_XLINE (dat, obj);
3635 break;
3636 case DWG_TYPE_DICTIONARY:
3637 error = dwg_encode_DICTIONARY (dat, obj);
3638 break;
3639 case DWG_TYPE_MTEXT:
3640 error = dwg_encode_MTEXT (dat, obj);
3641 break;
3642 case DWG_TYPE_LEADER:
3643 error = dwg_encode_LEADER (dat, obj);
3644 break;
3645 case DWG_TYPE_TOLERANCE:
3646 error = dwg_encode_TOLERANCE (dat, obj);
3647 break;
3648 case DWG_TYPE_MLINE:
3649 error = dwg_encode_MLINE (dat, obj);
3650 break;
3651 case DWG_TYPE_BLOCK_CONTROL:
3652 error = dwg_encode_BLOCK_CONTROL (dat, obj);
3653 break;
3654 case DWG_TYPE_BLOCK_HEADER:
3655 error = dwg_encode_BLOCK_HEADER (dat, obj);
3656 break;
3657 case DWG_TYPE_LAYER_CONTROL:
3658 error = dwg_encode_LAYER_CONTROL (dat, obj);
3659 break;
3660 case DWG_TYPE_LAYER:
3661 error = dwg_encode_LAYER (dat, obj);
3662 break;
3663 case DWG_TYPE_STYLE_CONTROL:
3664 error = dwg_encode_STYLE_CONTROL (dat, obj);
3665 break;
3666 case DWG_TYPE_STYLE:
3667 error = dwg_encode_STYLE (dat, obj);
3668 break;
3669 case DWG_TYPE_LTYPE_CONTROL:
3670 error = dwg_encode_LTYPE_CONTROL (dat, obj);
3671 break;
3672 case DWG_TYPE_LTYPE:
3673 error = dwg_encode_LTYPE (dat, obj);
3674 break;
3675 case DWG_TYPE_VIEW_CONTROL:
3676 error = dwg_encode_VIEW_CONTROL (dat, obj);
3677 break;
3678 case DWG_TYPE_VIEW:
3679 error = dwg_encode_VIEW (dat, obj);
3680 break;
3681 case DWG_TYPE_UCS_CONTROL:
3682 error = dwg_encode_UCS_CONTROL (dat, obj);
3683 break;
3684 case DWG_TYPE_UCS:
3685 error = dwg_encode_UCS (dat, obj);
3686 break;
3687 case DWG_TYPE_VPORT_CONTROL:
3688 error = dwg_encode_VPORT_CONTROL (dat, obj);
3689 break;
3690 case DWG_TYPE_VPORT:
3691 error = dwg_encode_VPORT (dat, obj);
3692 break;
3693 case DWG_TYPE_APPID_CONTROL:
3694 error = dwg_encode_APPID_CONTROL (dat, obj);
3695 break;
3696 case DWG_TYPE_APPID:
3697 error = dwg_encode_APPID (dat, obj);
3698 break;
3699 case DWG_TYPE_DIMSTYLE_CONTROL:
3700 error = dwg_encode_DIMSTYLE_CONTROL (dat, obj);
3701 break;
3702 case DWG_TYPE_DIMSTYLE:
3703 error = dwg_encode_DIMSTYLE (dat, obj);
3704 break;
3705 case DWG_TYPE_VX_CONTROL:
3706 error = dwg_encode_VX_CONTROL (dat, obj);
3707 break;
3708 case DWG_TYPE_VX_TABLE_RECORD:
3709 error = dwg_encode_VX_TABLE_RECORD (dat, obj);
3710 break;
3711 case DWG_TYPE_GROUP:
3712 error = dwg_encode_GROUP (dat, obj);
3713 break;
3714 case DWG_TYPE_MLINESTYLE:
3715 error = dwg_encode_MLINESTYLE (dat, obj);
3716 (void)dwg_encode_get_class (dwg, obj);
3717 break;
3718 case DWG_TYPE_OLE2FRAME:
3719 error = dwg_encode_OLE2FRAME (dat, obj);
3720 (void)dwg_encode_get_class (dwg, obj);
3721 break;
3722 case DWG_TYPE_DUMMY:
3723 error = dwg_encode_DUMMY (dat, obj);
3724 break;
3725 case DWG_TYPE_LONG_TRANSACTION:
3726 error = dwg_encode_LONG_TRANSACTION (dat, obj);
3727 break;
3728 case DWG_TYPE_LWPOLYLINE:
3729 error = dwg_encode_LWPOLYLINE (dat, obj);
3730 (void)dwg_encode_get_class (dwg, obj);
3731 break;
3732 case DWG_TYPE_HATCH:
3733 error = dwg_encode_HATCH (dat, obj);
3734 (void)dwg_encode_get_class (dwg, obj);
3735 break;
3736 case DWG_TYPE_XRECORD:
3737 error = dwg_encode_XRECORD (dat, obj);
3738 (void)dwg_encode_get_class (dwg, obj);
3739 break;
3740 case DWG_TYPE_PLACEHOLDER:
3741 error = dwg_encode_PLACEHOLDER (dat, obj);
3742 (void)dwg_encode_get_class (dwg, obj);
3743 break;
3744 case DWG_TYPE_OLEFRAME:
3745 error = dwg_encode_OLEFRAME (dat, obj);
3746 (void)dwg_encode_get_class (dwg, obj);
3747 break;
3748 case DWG_TYPE_VBA_PROJECT:
3749 //LOG_ERROR ("Unhandled Object VBA_PROJECT. Has its own AcDb::VBAProject section");
3750 error = dwg_encode_VBA_PROJECT (dat, obj);
3751 (void)dwg_encode_get_class (dwg, obj);
3752 break;
3753 case DWG_TYPE_LAYOUT:
3754 error |= dwg_encode_LAYOUT (dat, obj);
3755 (void)dwg_encode_get_class (dwg, obj);
3756 break;
3757 case DWG_TYPE_PROXY_ENTITY:
3758 error = dwg_encode_PROXY_ENTITY (dat, obj);
3759 break;
3760 case DWG_TYPE_PROXY_OBJECT:
3761 error = dwg_encode_PROXY_OBJECT (dat, obj);
3762 break;
3763 default:
3764 if (dwg && obj->type == dwg->layout_type
3765 && obj->fixedtype == DWG_TYPE_LAYOUT)
3766 {
3767 error = dwg_encode_LAYOUT (dat, obj);
3768 (void)dwg_encode_get_class (dwg, obj);
3769 }
3770 else if (dwg != NULL
3771 && (error = dwg_encode_variable_type (dwg, dat, obj))
3772 & DWG_ERR_UNHANDLEDCLASS)
3773 {
3774 int is_entity;
3775 Dwg_Class *klass = dwg_encode_get_class (dwg, obj);
3776 if (klass)
3777 is_entity = klass->item_class_id == 0x1f2
3778 && obj->supertype == DWG_SUPERTYPE_ENTITY;
3779 else
3780 is_entity = obj->supertype == DWG_SUPERTYPE_ENTITY;
3781
3782 assert (address);
3783 dat->byte = address; // restart and write into the UNKNOWN_OBJ object
3784 dat->bit = 0;
3785
3786 bit_write_MS (dat, obj->size); // unknown blobs have a known size
3787 if (dat->version >= R_2010)
3788 {
3789 bit_write_UMC (dat, obj->handlestream_size);
3790 bit_write_BOT (dat, obj->type);
3791 }
3792 else
3793 bit_write_BS (dat, obj->type);
3794
3795 // from json and dwg can write to these. from dxf not.
3796 if (is_entity)
3797 {
3798 if (obj->bitsize && dwg->header.version == dwg->header.from_version)
3799 obj->was_bitsize_set = 1;
3800 error = dwg_encode_UNKNOWN_ENT (dat, obj);
3801 }
3802 else
3803 {
3804 // skip START_OBJECT_HANDLE_STREAM (see DWG_OBJECT_END)
3805 // unknown_bits already includes that.
3806 if (!obj->hdlpos)
3807 {
3808 if (obj->bitsize)
3809 {
3810 obj->hdlpos = (obj->address * 8) + obj->bitsize;
3811 if (dwg->header.version == dwg->header.from_version)
3812 obj->was_bitsize_set = 1;
3813 }
3814 else
3815 obj->hdlpos = (obj->address * 8) + obj->num_unknown_bits;
3816 }
3817 error = dwg_encode_UNKNOWN_OBJ (dat, obj);
3818 }
3819
3820 if (dwg->header.version == dwg->header.from_version
3821 && obj->unknown_bits && obj->num_unknown_bits) // cannot calculate
3822 {
3823 int len = obj->num_unknown_bits / 8;
3824 const int mod = obj->num_unknown_bits % 8;
3825 if (mod)
3826 len++;
3827 bit_write_TF (dat, obj->unknown_bits, len);
3828 LOG_TRACE ("unknown_bits: %d/%u [TF]\n", len, (unsigned)obj->num_unknown_bits);
3829 LOG_TRACE_TF (obj->unknown_bits, len);
3830 if (mod)
3831 bit_advance_position (dat, mod - 8);
3832 obj->was_bitsize_set = 1;
3833 }
3834 }
3835 }
3836
3837 /* DXF/JSON/RW across versions: patchup size and bitsize */
3838 /* Across versions size+bitsize must be recalculated.
3839 Sizes are unreliable when changing versions. */
3840 if (!obj->size || dwg->header.from_version != dwg->header.version
3841 || obj->was_bitsize_set)
3842 {
3843 BITCODE_BL pos = bit_position (dat);
3844 BITCODE_RL old_size = obj->size;
3845 if (dwg->header.version < R_2004 || obj->index)
3846 {
3847 if (!address)
3848 return DWG_ERR_INVALIDDWG;
3849 assert (address);
3850 }
3851 if (dat->byte > obj->address)
3852 {
3853 // The size and CRC fields are not included in the obj->size
3854 obj->size = dat->byte - obj->address;
3855 if (dat->bit)
3856 obj->size++;
3857 }
3858 if (dat->byte >= dat->size)
3859 bit_chain_alloc (dat);
3860 // assert (obj->bitsize); // on errors
3861 if (!obj->bitsize ||
3862 (dwg->header.from_version != dwg->header.version
3863 // and not calculated from HANDLE_STREAM or via unknown_bits already
3864 && !obj->was_bitsize_set))
3865 {
3866 LOG_TRACE ("-bitsize calc from address (no handle) @%lu.%u\n",
3867 dat->byte - obj->address, dat->bit);
3868 obj->bitsize = pos - (obj->address * 8);
3869 }
3870 bit_set_position (dat, address * 8);
3871 if (obj->size > 0x7fff && old_size <= 0x7fff)
3872 {
3873 // with overlarge sizes >0x7fff memmove dat right by 2, one more RS added.
3874 LOG_INFO ("overlarge size %u > 0x7fff @%lu\n", (unsigned)obj->size, dat->byte);
3875 if (dat->byte + obj->size + 2 >= dat->size)
3876 bit_chain_alloc (dat);
3877 memmove (&dat->chain[dat->byte + 2], &dat->chain[dat->byte], obj->size);
3878 obj->size += 2;
3879 obj->bitsize += 16;
3880 obj->bitsize_pos += 16;
3881 pos += 16;
3882 }
3883 if (obj->size <= 0x7fff && old_size > 0x7fff)
3884 {
3885 // with old overlarge sizes >0x7fff memmove dat left by 2, one RS removed.
3886 LOG_INFO ("was overlarge size %u < 0x7fff @%lu\n", (unsigned)old_size, dat->byte);
3887 memmove (&dat->chain[dat->byte], &dat->chain[dat->byte + 2], obj->size);
3888 obj->size -= 2;
3889 obj->bitsize -= 16;
3890 obj->bitsize_pos -= 16;
3891 pos -= 16;
3892 }
3893 bit_write_MS (dat, obj->size);
3894 LOG_TRACE ("-size: %u [MS] @%lu\n", obj->size, address);
3895 SINCE (R_2013)
3896 {
3897 if (!obj->handlestream_size && obj->bitsize)
3898 obj->handlestream_size = (obj->size * 8) - obj->bitsize;
3899 bit_write_UMC (dat, obj->handlestream_size);
3900 LOG_TRACE ("-handlestream_size: %lu [UMC]\n", obj->handlestream_size);
3901 }
3902 SINCE (R_2000)
3903 {
3904 if (obj->bitsize_pos && obj->bitsize)
3905 {
3906 bit_set_position (dat, obj->bitsize_pos);
3907 bit_write_RL (dat, obj->bitsize);
3908 LOG_TRACE ("-bitsize: %u [RL] @%lu.%lu\n", obj->bitsize,
3909 obj->bitsize_pos / 8, obj->bitsize_pos % 8);
3910 }
3911 }
3912 bit_set_position (dat, pos);
3913 }
3914
3915 /* Now 1 padding bits until next byte, and then a RS CRC */
3916 if (dat->bit)
3917 LOG_TRACE ("padding: +%d [*B]\n", 8 - dat->bit)
3918 while (dat->bit)
3919 bit_write_B (dat, 1);
3920 end_address = obj->address + obj->size;
3921 if (end_address != dat->byte)
3922 {
3923 if (obj->size)
3924 LOG_WARN ("Wrong object size: %lu + %u = %lu != %lu: %ld off",
3925 address, obj->size, end_address, dat->byte,
3926 (long)(end_address - dat->byte));
3927 //dat->byte = end_address;
3928 }
3929 assert (!dat->bit);
3930 bit_write_CRC (dat, address, 0xC0C1);
3931 return error;
3932 }
3933
3934 /** writes the data part, if there's no raw.
3935 */
3936 static int
dwg_encode_eed_data(Bit_Chain * restrict dat,Dwg_Eed_Data * restrict data,const int i)3937 dwg_encode_eed_data (Bit_Chain *restrict dat, Dwg_Eed_Data *restrict data, const int i)
3938 {
3939 unsigned long pos = bit_position (dat);
3940 unsigned long size;
3941 bit_write_RC (dat, data->code);
3942 LOG_TRACE ("EED[%d] code: %d [RC] ", i, data->code);
3943 switch (data->code)
3944 {
3945 case 0:
3946 {
3947 PRE (R_2007)
3948 {
3949 // only if from r2007+ DWG, not JSON, DXF
3950 if (data->u.eed_0.is_tu)
3951 {
3952 BITCODE_RS length = data->u.eed_0_r2007.length;
3953 BITCODE_RS *s = (BITCODE_RS *)&data->u.eed_0_r2007.string;
3954 BITCODE_RS codepage = 30; //FIXME
3955 char *dest;
3956 if (length + 5 + dat->byte >= dat->size)
3957 bit_chain_alloc (dat);
3958 if (length > 255)
3959 {
3960 LOG_ERROR ("eed: overlong string %d stripped", (int)length);
3961 length = 255;
3962 }
3963 dest = bit_embed_TU_size (s, length);
3964 bit_write_RC (dat, length);
3965 bit_write_RS_LE (dat, codepage);
3966 bit_write_TF (dat, (unsigned char *)dest, length);
3967 LOG_TRACE ("string: len=%d [RC] cp=%d [RS_LE] \"%s\" [TF]",
3968 length, codepage, dest);
3969 free (dest);
3970 }
3971 else
3972 {
3973 if (!*data->u.eed_0.string)
3974 data->u.eed_0.length = 0;
3975 if (data->u.eed_0.length + 5 + dat->byte >= dat->size)
3976 bit_chain_alloc (dat);
3977 bit_write_RC (dat, data->u.eed_0.length);
3978 bit_write_RS_LE (dat, data->u.eed_0.codepage);
3979 bit_write_TF (dat, (BITCODE_TF)data->u.eed_0.string, data->u.eed_0.length);
3980 LOG_TRACE ("string: len=%d [RC] cp=%d [RS_LE] \"%s\" [TF]",
3981 data->u.eed_0.length, data->u.eed_0.codepage,
3982 data->u.eed_0.string);
3983 }
3984 }
3985 LATER_VERSIONS
3986 {
3987 // from ASCII DWG or JSON, DXF
3988 if (!data->u.eed_0.is_tu)
3989 {
3990 BITCODE_RS length = data->u.eed_0.length;
3991 BITCODE_TU dest = bit_utf8_to_TU (data->u.eed_0.string, 0);
3992 if ((length * 2) + 5 + dat->byte >= dat->size)
3993 bit_chain_alloc (dat);
3994 bit_write_RS (dat, length);
3995 for (int j = 0; j < length; j++)
3996 bit_write_RS (dat, *dest++);
3997 data->u.eed_0_r2007.length = length;
3998 LOG_TRACE ("wstring: len=%d [RS] \"%s\" [TU]",
3999 (int)length, data->u.eed_0.string);
4000 }
4001 else
4002 {
4003 BITCODE_RS length = data->u.eed_0_r2007.length;
4004 BITCODE_RS *s = (BITCODE_RS *)&data->u.eed_0_r2007.string;
4005 if ((length * 2) + 5 + dat->byte >= dat->size)
4006 bit_chain_alloc (dat);
4007 bit_write_RS (dat, length);
4008 for (int j = 0; j < length; j++)
4009 bit_write_RS (dat, *s++);
4010 #ifdef _WIN32
4011 LOG_TRACE ("wstring: len=%d [RS] \"" FORMAT_TU "\" [TU]",
4012 (int)data->u.eed_0_r2007.length,
4013 data->u.eed_0_r2007.string);
4014 #else
4015 if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE)
4016 {
4017 char *u8 = bit_TU_to_utf8_len (data->u.eed_0_r2007.string,
4018 data->u.eed_0_r2007.length);
4019 LOG_TRACE ("wstring: len=%d [RS] \"%s\" [TU]",
4020 (int)data->u.eed_0_r2007.length, u8);
4021 free (u8);
4022 }
4023 #endif
4024 }
4025 }
4026 }
4027 break;
4028 case 2:
4029 bit_write_RC (dat, data->u.eed_2.close);
4030 LOG_TRACE ("close: %d [RC]", (int)data->u.eed_2.close);
4031 break;
4032 case 3:
4033 bit_write_RLL (dat, data->u.eed_3.layer);
4034 LOG_TRACE ("layer: 0x%lX [RLL]", (unsigned long)data->u.eed_3.layer);
4035 break;
4036 case 4:
4037 bit_write_RC (dat, data->u.eed_4.length);
4038 bit_write_TF (dat, (BITCODE_TF)data->u.eed_4.data,
4039 data->u.eed_4.length);
4040 LOG_TRACE ("binary: ");
4041 LOG_TRACE_TF (data->u.eed_4.data, data->u.eed_4.length);
4042 break;
4043 case 5:
4044 bit_write_RLL (dat, (BITCODE_RLL)data->u.eed_5.entity);
4045 LOG_TRACE ("entity: 0x%lX [ulong]", data->u.eed_5.entity);
4046 break;
4047 case 10:
4048 case 11:
4049 case 12:
4050 case 13:
4051 case 14:
4052 case 15:
4053 bit_write_RD (dat, data->u.eed_10.point.x);
4054 bit_write_RD (dat, data->u.eed_10.point.y);
4055 bit_write_RD (dat, data->u.eed_10.point.z);
4056 LOG_TRACE ("3dpoint: (%f, %f, %f) [3RD]", data->u.eed_10.point.x,
4057 data->u.eed_10.point.y, data->u.eed_10.point.z);
4058 break;
4059 case 40:
4060 case 41:
4061 case 42:
4062 bit_write_RD (dat, data->u.eed_40.real);
4063 LOG_TRACE ("real: %f [RD]", data->u.eed_40.real);
4064 break;
4065 case 70:
4066 bit_write_RS (dat, data->u.eed_70.rs);
4067 LOG_TRACE ("short: " FORMAT_RS " [RS]", data->u.eed_70.rs);
4068 break;
4069 case 71:
4070 bit_write_RL (dat, data->u.eed_71.rl);
4071 LOG_TRACE ("long: " FORMAT_RL " [RL]", data->u.eed_71.rl);
4072 break;
4073 default:
4074 dat->byte--;
4075 LOG_ERROR ("unknown EED code %d", data->code);
4076 }
4077 size = bit_position (dat) - pos;
4078 return (size % 8) ? (int)(size / 8) + 1 : (int)(size / 8);
4079 }
4080
4081 #define dat_flush(orig, dat) bit_copy_chain (orig, dat)
4082
4083 /** Either writes the raw part.
4084 Only members with size have raw and a handle.
4085 Otherwise (indxf) defer to dwg_encode_eed_data.
4086 On does_cross_unicode_datversion skip raw, and recalc the sizes.
4087 */
4088 static int
dwg_encode_eed(Bit_Chain * restrict dat,Dwg_Object * restrict obj)4089 dwg_encode_eed (Bit_Chain *restrict dat, Dwg_Object *restrict obj)
4090 {
4091 //unsigned long off = obj->address;
4092 //unsigned dat_size = 0;
4093 Dwg_Handle *last_handle = NULL;
4094 Bit_Chain dat1 = { 0 };
4095 int i, num_eed = obj->tio.object->num_eed;
4096 BITCODE_BS size = 0;
4097 int last_size = 0;
4098 int new_size = 0;
4099 int did_raw = 0;
4100 int need_recalc = does_cross_unicode_datversion (dat);
4101
4102 bit_chain_init (&dat1, 1024);
4103 dat1.from_version = dat->from_version;
4104 dat1.version = dat->version;
4105 dat1.opts = dat->opts;
4106
4107 // Skip DICTIONARY AE3 AcDsRecords/AcDsSchemas 1070 . 2, wrong ACIS version
4108 if (dat->opts & DWG_OPTS_INDXF &&
4109 dat->version < R_2007 &&
4110 obj->fixedtype == DWG_TYPE_DICTIONARY &&
4111 num_eed == 1)
4112 {
4113 Dwg_Eed *eed = &obj->tio.object->eed[0];
4114 if (eed->handle.value == 0x12 &&
4115 eed->data->code == 70 &&
4116 eed->data->u.eed_70.rs > 1)
4117 {
4118 LOG_TRACE ("skip AcDs DICTIONARY EED to use ACIS ver 2\n");
4119 num_eed = 0;
4120 }
4121 }
4122
4123 for (i = 0; i < num_eed; i++)
4124 {
4125 Dwg_Eed *eed = &obj->tio.object->eed[i];
4126 if (eed->size) // start of a new EED appid section
4127 {
4128 size = eed->size;
4129 if (eed->raw && !need_recalc)
4130 {
4131 did_raw = 1;
4132 bit_write_BS (dat, size);
4133 LOG_TRACE ("EED[%d] size: " FORMAT_BS " [BS]", i, size); LOG_POS
4134 bit_write_H (dat, &eed->handle);
4135 LOG_TRACE ("EED[%d] handle: " FORMAT_H " [H]", i,
4136 ARGS_H (eed->handle)); LOG_POS
4137 LOG_TRACE ("EED[%d] raw [TF %d]\n", i, size);
4138 bit_write_TF (dat, eed->raw, size);
4139 LOG_TRACE_TF (eed->raw, size);
4140 new_size = 0;
4141 }
4142 // indxf
4143 else if (eed->data)
4144 {
4145 did_raw = 0;
4146 if (new_size) // flush old
4147 {
4148
4149 // FIXME DXF import of ACAD EED crashes (GH #244)
4150 // on BLOCK_HEADER with 0 . "DesignCenter Data"
4151 #define EED_ALLOWED !(dat->opts & DWG_OPTS_INDXF) || last_handle->value != 0x12 \
4152 || obj->fixedtype != DWG_TYPE_BLOCK_HEADER
4153
4154 if (EED_ALLOWED)
4155 {
4156 eed->size = new_size;
4157 bit_write_BS (dat, new_size);
4158 LOG_TRACE ("EED[%d] size: " FORMAT_BS " [BS]", last_size, new_size); LOG_POS;
4159 bit_write_H (dat, last_handle);
4160 LOG_TRACE ("EED[%d] handle: " FORMAT_H " [H]", last_size,
4161 ARGS_H (*last_handle)); LOG_POS;
4162 LOG_TRACE ("flush eed_data %lu.%d\n", dat1.byte, dat1.bit);
4163 dat_flush (dat, &dat1);
4164 }
4165 else
4166 {
4167 LOG_WARN ("skip EED[%d] handle: " FORMAT_H " [H] for DesignCenter Data", last_size,
4168 ARGS_H (*last_handle)); LOG_POS;
4169 dat1.byte = 0;
4170 }
4171 new_size = 0;
4172 }
4173 new_size = dwg_encode_eed_data (&dat1, eed->data, i);
4174 LOG_POS;
4175 }
4176 last_size = i;
4177 last_handle = &eed->handle;
4178 }
4179 // and if not already written by the previous raw (this has size=0)
4180 else if (!did_raw && eed->data)
4181 {
4182 new_size += dwg_encode_eed_data (&dat1, eed->data, i);
4183 LOG_POS;
4184 }
4185 }
4186 if (new_size && last_handle) // flush remaining rest
4187 {
4188 // FIXME HACK, see above
4189 if (EED_ALLOWED)
4190 {
4191 bit_write_BS (dat, new_size);
4192 LOG_TRACE ("EED[%d] size: " FORMAT_BS " [BS]", last_size, new_size); LOG_POS;
4193 bit_write_H (dat, last_handle);
4194 LOG_TRACE ("EED[%d] handle: " FORMAT_H " [H]", last_size,
4195 ARGS_H (*last_handle)); LOG_POS;
4196 last_handle = NULL;
4197 }
4198 else
4199 {
4200 LOG_TRACE ("skip EED[%d] handle: " FORMAT_H " [H] for DesignCenter Data", last_size,
4201 ARGS_H (*last_handle)); LOG_POS;
4202 dat1.byte = 0;
4203 }
4204 }
4205 if (dat1.byte)
4206 LOG_TRACE ("flush eed_data %lu.%d\n", dat1.byte, dat1.bit);
4207 dat_flush (dat, &dat1);
4208 bit_write_BS (dat, 0);
4209 if (i)
4210 LOG_TRACE ("EED[%d] size: 0 [BS] (end)\n", i);
4211 LOG_TRACE ("num_eed: %d\n", num_eed);
4212 bit_chain_free (&dat1);
4213 return 0;
4214 }
4215
4216 /* The first common part of every entity.
4217
4218 The last common part is common_entity_handle_data.spec
4219 which is read from the hdl stream.
4220 See DWG_SUPERTYPE_ENTITY in dwg_encode().
4221 */
4222 static int
dwg_encode_entity(Dwg_Object * restrict obj,Bit_Chain * dat,Bit_Chain * restrict hdl_dat,Bit_Chain * str_dat)4223 dwg_encode_entity (Dwg_Object *restrict obj, Bit_Chain *dat,
4224 Bit_Chain *restrict hdl_dat, Bit_Chain *str_dat)
4225 {
4226 int error = 0;
4227 Dwg_Object_Entity *ent = obj->tio.entity;
4228 Dwg_Object_Entity *_obj = ent;
4229 Dwg_Data *dwg = ent->dwg;
4230
4231 if (!obj || !dat || !ent)
4232 return DWG_ERR_INVALIDDWG;
4233
4234 hdl_dat->from_version = dat->from_version;
4235 hdl_dat->version = dat->version;
4236 hdl_dat->opts = dat->opts;
4237
4238 PRE (R_13)
4239 {
4240
4241 if (FIELD_VALUE (flag_r11) & 4 && FIELD_VALUE (kind_r11) > 2
4242 && FIELD_VALUE (kind_r11) != 22)
4243 FIELD_RD (elevation_r11, 30);
4244 if (FIELD_VALUE (flag_r11) & 8)
4245 FIELD_RD (thickness_r11, 39);
4246 if (FIELD_VALUE (flag_r11) & 0x20)
4247 {
4248 Dwg_Object_Ref *hdl
4249 = dwg_decode_handleref_with_code (dat, obj, dwg, 0);
4250 if (hdl)
4251 obj->handle = hdl->handleref;
4252 }
4253 if (FIELD_VALUE (extra_r11) & 4)
4254 FIELD_RS (paper_r11, 0);
4255 }
4256
4257 SINCE (R_2007) { *str_dat = *dat; }
4258 VERSIONS (R_2000, R_2007)
4259 {
4260 obj->bitsize_pos = bit_position (dat);
4261 bit_write_RL (dat, obj->bitsize);
4262 LOG_TRACE ("bitsize: %u [RL] (@%lu.%lu)\n", obj->bitsize,
4263 obj->bitsize_pos / 8, obj->bitsize_pos % 8);
4264 }
4265 obj->was_bitsize_set = 0;
4266 if (obj->bitsize)
4267 {
4268 obj->hdlpos = (obj->address * 8) + obj->bitsize;
4269 }
4270 SINCE (R_2007)
4271 {
4272 // The handle stream offset, i.e. end of the object, right after
4273 // the has_strings bit.
4274 SINCE (R_2010)
4275 {
4276 if (obj->bitsize)
4277 {
4278 obj->hdlpos += 8;
4279 // LOG_HANDLE ("(bitsize: " FORMAT_RL ", ", obj->bitsize);
4280 LOG_HANDLE ("hdlpos: %lu\n", obj->hdlpos);
4281 }
4282 }
4283 // and set the string stream (restricted to size)
4284 error |= obj_string_stream (dat, obj, str_dat);
4285 }
4286
4287 bit_write_H (dat, &obj->handle);
4288 LOG_TRACE ("handle: " FORMAT_H " [H 5]", ARGS_H (obj->handle))
4289 LOG_INSANE (" @%lu.%u", dat->byte - obj->address, dat->bit)
4290 LOG_TRACE ("\n")
4291 PRE (R_13) { return DWG_ERR_NOTYETSUPPORTED; }
4292
4293 error |= dwg_encode_eed (dat, obj);
4294 // if (error & (DWG_ERR_INVALIDTYPE|DWG_ERR_VALUEOUTOFBOUNDS))
4295 // return error;
4296
4297 // clang-format off
4298 #include "common_entity_data.spec"
4299 // clang-format on
4300
4301 return error;
4302 }
4303
4304 static int
dwg_encode_common_entity_handle_data(Bit_Chain * dat,Bit_Chain * hdl_dat,Dwg_Object * restrict obj)4305 dwg_encode_common_entity_handle_data (Bit_Chain *dat, Bit_Chain *hdl_dat,
4306 Dwg_Object *restrict obj)
4307 {
4308 Dwg_Object_Entity *ent;
4309 // Dwg_Data *dwg = obj->parent;
4310 Dwg_Object_Entity *_obj;
4311 BITCODE_BL vcount;
4312 int error = 0;
4313 ent = obj->tio.entity;
4314 _obj = ent;
4315
4316 // clang-format off
4317 #include "common_entity_handle_data.spec"
4318 // clang-format on
4319
4320 return error;
4321 }
4322
4323
4324 void
dwg_encode_handleref(Bit_Chain * hdl_dat,Dwg_Object * restrict obj,Dwg_Data * restrict dwg,Dwg_Object_Ref * restrict ref)4325 dwg_encode_handleref (Bit_Chain *hdl_dat, Dwg_Object *restrict obj,
4326 Dwg_Data *restrict dwg, Dwg_Object_Ref *restrict ref)
4327 {
4328 // this function should receive a Object_Ref without an abs_ref, calculate it
4329 // and return a Dwg_Handle this should be a higher level function not sure if
4330 // the prototype is correct
4331 assert (obj);
4332 }
4333
4334 /**
4335 * code:
4336 * TYPEDOBJHANDLE:
4337 * 2 Soft owner
4338 * 3 Hard owner
4339 * 4 Soft pointer
4340 * 5 Hard pointer
4341 * OFFSETOBJHANDLE for soft owners or pointers:
4342 * 6 ref + 1
4343 * 8 ref - 1
4344 * a ref + offset
4345 * c ref - offset
4346 */
4347 void
dwg_encode_handleref_with_code(Bit_Chain * hdl_dat,Dwg_Object * restrict obj,Dwg_Data * restrict dwg,Dwg_Object_Ref * restrict ref,unsigned int code)4348 dwg_encode_handleref_with_code (Bit_Chain *hdl_dat, Dwg_Object *restrict obj,
4349 Dwg_Data *restrict dwg,
4350 Dwg_Object_Ref *restrict ref,
4351 unsigned int code)
4352 {
4353 // XXX fixme. create the handle, then check the code. allow relative handle
4354 // soft codes.
4355 dwg_encode_handleref (hdl_dat, obj, dwg, ref);
4356 if (ref->absolute_ref == 0 && ref->handleref.code != code)
4357 {
4358 /*
4359 * With TYPEDOBJHANDLE 2-5 the code indicates the type of ownership.
4360 * With OFFSETOBJHANDLE >5 the handle is stored as an offset from some
4361 * other handle.
4362 */
4363 switch (ref->handleref.code)
4364 {
4365 case 0x06:
4366 ref->absolute_ref = (obj->handle.value + 1);
4367 break;
4368 case 0x08:
4369 ref->absolute_ref = (obj->handle.value - 1);
4370 break;
4371 case 0x0A:
4372 ref->absolute_ref = (obj->handle.value + ref->handleref.value);
4373 break;
4374 case 0x0C:
4375 ref->absolute_ref = (obj->handle.value - ref->handleref.value);
4376 break;
4377 case 2:
4378 case 3:
4379 case 4:
4380 case 5:
4381 ref->absolute_ref = ref->handleref.value;
4382 break;
4383 case 0: // ignore (ANYCODE)
4384 ref->absolute_ref = ref->handleref.value;
4385 break;
4386 default:
4387 LOG_WARN ("Invalid handle pointer code %d", ref->handleref.code);
4388 break;
4389 }
4390 }
4391 }
4392
4393 /* The first common part of every object.
4394
4395 There is no COMMON_ENTITY_DATA for objects, handles are deferred and flushed later.
4396 See DWG_SUPERTYPE_OBJECT in dwg_encode().
4397 */
4398 static int
dwg_encode_object(Dwg_Object * restrict obj,Bit_Chain * dat,Bit_Chain * restrict hdl_dat,Bit_Chain * str_dat)4399 dwg_encode_object (Dwg_Object *restrict obj, Bit_Chain *dat,
4400 Bit_Chain *restrict hdl_dat, Bit_Chain *str_dat)
4401 {
4402 int error = 0;
4403 BITCODE_BL vcount;
4404
4405 hdl_dat->from_version = dat->from_version;
4406 hdl_dat->version = dat->version;
4407 hdl_dat->opts = dat->opts;
4408
4409 {
4410 Dwg_Object *_obj = obj;
4411 VERSIONS (R_2000, R_2007)
4412 {
4413 obj->bitsize_pos = bit_position (dat);
4414 FIELD_RL (bitsize, 0);
4415 }
4416 obj->was_bitsize_set = 0;
4417 if (obj->bitsize)
4418 // the handle stream offset
4419 obj->hdlpos = bit_position (dat) + obj->bitsize;
4420 SINCE (R_2007) { obj_string_stream (dat, obj, str_dat); }
4421 if (!_obj || !obj->tio.object)
4422 return DWG_ERR_INVALIDDWG;
4423
4424 bit_write_H (dat, &obj->handle);
4425 LOG_TRACE ("handle: " FORMAT_H " [H 5]\n", ARGS_H (obj->handle));
4426 error |= dwg_encode_eed (dat, obj);
4427
4428 VERSIONS (R_13, R_14)
4429 {
4430 obj->bitsize_pos = bit_position (dat);
4431 FIELD_RL (bitsize, 0);
4432 }
4433 }
4434
4435 SINCE (R_13) {
4436 Dwg_Object_Object *_obj = obj->tio.object;
4437 FIELD_BL (num_reactors, 0);
4438 SINCE (R_2004) { FIELD_B (is_xdic_missing, 0); }
4439 SINCE (R_2013) { FIELD_B (has_ds_data, 0); } // AcDs DATA
4440 }
4441 return error;
4442 }
4443
4444 AFL_GCC_TOOBIG
4445 static int
dwg_encode_header_variables(Bit_Chain * dat,Bit_Chain * hdl_dat,Bit_Chain * str_dat,Dwg_Data * restrict dwg)4446 dwg_encode_header_variables (Bit_Chain *dat, Bit_Chain *hdl_dat,
4447 Bit_Chain *str_dat, Dwg_Data *restrict dwg)
4448 {
4449 Dwg_Header_Variables *_obj = &dwg->header_vars;
4450 Dwg_Object *obj = NULL;
4451 Dwg_Version_Type old_from = dat->from_version;
4452
4453 if (!_obj->HANDSEED) // minimal or broken DXF
4454 {
4455 BITCODE_H last_hdl;
4456 unsigned long seed = 0;
4457 dwg->opts |= DWG_OPTS_MINIMAL;
4458 dat->from_version = (Dwg_Version_Type)((int)dat->version - 1);
4459 LOG_TRACE ("encode from minimal DXF\n");
4460
4461 _obj->HANDSEED = (Dwg_Object_Ref*)calloc (1, sizeof (Dwg_Object_Ref));
4462 // check the object map for the next available handle
4463 last_hdl = dwg->num_object_refs ? dwg->object_ref[ dwg->num_object_refs - 1] : NULL;
4464 if (last_hdl)
4465 {
4466 // find the largest handle
4467 seed = last_hdl->absolute_ref;
4468 LOG_TRACE ("compute HANDSEED %lu ", seed);
4469 for (unsigned i = 0; i < dwg->num_object_refs; i++)
4470 {
4471 Dwg_Object_Ref *ref = dwg->object_ref[i];
4472 if (ref->absolute_ref > seed)
4473 seed = ref->absolute_ref;
4474 }
4475 _obj->HANDSEED->absolute_ref = seed + 1;
4476 LOG_TRACE ("-> %lu\n", seed);
4477 }
4478 else
4479 _obj->HANDSEED->absolute_ref = 0x72E;
4480 }
4481
4482 // clang-format off
4483 #include "header_variables.spec"
4484 // clang-format on
4485
4486 dat->from_version = old_from;
4487 return 0;
4488 }
4489 AFL_GCC_POP
4490
4491 static int
dwg_encode_xdata(Bit_Chain * restrict dat,Dwg_Object_XRECORD * restrict _obj,unsigned xdata_size)4492 dwg_encode_xdata (Bit_Chain *restrict dat, Dwg_Object_XRECORD *restrict _obj,
4493 unsigned xdata_size)
4494 {
4495 Dwg_Resbuf *rbuf = _obj->xdata;
4496 enum RESBUF_VALUE_TYPE type;
4497 int error = 0;
4498 int i;
4499 unsigned j = 0;
4500 //BITCODE_BL num_xdata = _obj->num_xdata;
4501 unsigned long start = dat->byte, end = start + xdata_size;
4502 Dwg_Data *dwg = _obj->parent->dwg;
4503 Dwg_Object *obj = &dwg->object[_obj->parent->objid];
4504
4505 if (dat->opts & DWG_OPTS_IN) // loosen the overflow checks on dxf/json imports
4506 end += xdata_size;
4507
4508 while (rbuf)
4509 {
4510 bit_write_RS (dat, rbuf->type);
4511 LOG_INSANE ("xdata[%u] type: " FORMAT_RS " [RS] @%lu.%u\n", j,
4512 rbuf->type, dat->byte - obj->address, dat->bit)
4513 type = dwg_resbuf_value_type (rbuf->type);
4514 switch (type)
4515 {
4516 case DWG_VT_STRING:
4517 PRE (R_2007)
4518 {
4519 if (dat->byte + 3 + rbuf->value.str.size > end)
4520 break;
4521 // from TU DWG only
4522 if (rbuf->value.str.size && rbuf->value.str.is_tu)
4523 {
4524 BITCODE_TV new = bit_embed_TU_size (rbuf->value.str.u.wdata,
4525 rbuf->value.str.size);
4526 int len = strlen(new);
4527 bit_write_RS (dat, len);
4528 bit_write_RC (dat, rbuf->value.str.codepage);
4529 if (rbuf->value.str.u.data)
4530 bit_write_TF (dat, (BITCODE_TF)new, len);
4531 else
4532 bit_write_TF (dat, (BITCODE_TF)"", 0);
4533 LOG_TRACE ("xdata[%u]: \"%s\" [TF %d %d]", j,
4534 rbuf->value.str.u.data, len, rbuf->type);
4535 free (new);
4536 }
4537 else
4538 {
4539 bit_write_RS (dat, rbuf->value.str.size);
4540 bit_write_RC (dat, rbuf->value.str.codepage);
4541 if (rbuf->value.str.u.data)
4542 bit_write_TF (dat, (BITCODE_TF)rbuf->value.str.u.data, rbuf->value.str.size);
4543 else
4544 bit_write_TF (dat, (BITCODE_TF)"", 0);
4545 LOG_TRACE ("xdata[%u]: \"%s\" [TF %d %d]", j,
4546 rbuf->value.str.u.data, rbuf->value.str.size, rbuf->type);
4547 }
4548 LOG_POS;
4549 }
4550 LATER_VERSIONS
4551 {
4552 if (dat->byte + 2 + (2 * rbuf->value.str.size) > end)
4553 break;
4554 if (rbuf->value.str.size && !rbuf->value.str.is_tu)
4555 {
4556 // TODO: same len when converted to TU? normally yes
4557 BITCODE_TU new = bit_utf8_to_TU (rbuf->value.str.u.data, 0);
4558 bit_write_RS (dat, rbuf->value.str.size);
4559 for (i = 0; i < rbuf->value.str.size; i++)
4560 bit_write_RS (dat, new[i]);
4561 LOG_TRACE_TU ("xdata", new, rbuf->type);
4562 free (new);
4563 }
4564 else
4565 {
4566 bit_write_RS (dat, rbuf->value.str.size);
4567 for (i = 0; i < rbuf->value.str.size; i++)
4568 bit_write_RS (dat, rbuf->value.str.u.wdata[i]);
4569 LOG_TRACE_TU ("xdata", rbuf->value.str.u.wdata, rbuf->type);
4570 }
4571 LOG_POS;
4572 }
4573 break;
4574 case DWG_VT_REAL:
4575 if (dat->byte + 8 > end)
4576 break;
4577 bit_write_RD (dat, rbuf->value.dbl);
4578 LOG_TRACE ("xdata[%u]: %f [RD %d]", j, rbuf->value.dbl,
4579 rbuf->type);
4580 LOG_POS;
4581 break;
4582 case DWG_VT_BOOL:
4583 case DWG_VT_INT8:
4584 bit_write_RC (dat, rbuf->value.i8);
4585 LOG_TRACE ("xdata[%u]: %d [RC %d]", j, (int)rbuf->value.i8,
4586 rbuf->type);
4587 LOG_POS;
4588 break;
4589 case DWG_VT_INT16:
4590 if (dat->byte + 2 > end)
4591 break;
4592 bit_write_RS (dat, rbuf->value.i16);
4593 LOG_TRACE ("xdata[%u]: %d [RS %d]", j, (int)rbuf->value.i16,
4594 rbuf->type);
4595 LOG_POS;
4596 break;
4597 case DWG_VT_INT32:
4598 if (dat->byte + 4 > end)
4599 break;
4600 bit_write_RL (dat, rbuf->value.i32);
4601 LOG_TRACE ("xdata[%d]: %ld [RL %d]", j, (long)rbuf->value.i32,
4602 rbuf->type);
4603 LOG_POS;
4604 break;
4605 case DWG_VT_INT64:
4606 if (dat->byte + 8 > end)
4607 break;
4608 bit_write_RLL (dat, rbuf->value.i64);
4609 LOG_TRACE ("xdata[%u]: " FORMAT_RLL " [RLL %d]", j,
4610 rbuf->value.i64, rbuf->type);
4611 LOG_POS;
4612 break;
4613 case DWG_VT_POINT3D:
4614 if (dat->byte + 24 > end)
4615 break;
4616 bit_write_RD (dat, rbuf->value.pt[0]);
4617 bit_write_RD (dat, rbuf->value.pt[1]);
4618 bit_write_RD (dat, rbuf->value.pt[2]);
4619 LOG_TRACE ("xdata[%u]: (%f,%f,%f) [3RD %d]", j, rbuf->value.pt[0],
4620 rbuf->value.pt[1], rbuf->value.pt[2], rbuf->type);
4621 LOG_POS;
4622 break;
4623 case DWG_VT_BINARY:
4624 if (dat->byte + rbuf->value.str.size > end)
4625 break;
4626 // 128 is a tradeoff, which of both data is wrong or right.
4627 if (!rbuf->value.str.u.data && rbuf->value.str.size > 128)
4628 {
4629 LOG_ERROR("Empty xdata string. Write size %u as 0", (unsigned)rbuf->value.str.size);
4630 bit_write_RC (dat, 0);
4631 }
4632 else
4633 bit_write_RC (dat, rbuf->value.str.size);
4634 if (rbuf->value.str.size)
4635 bit_write_TF (dat, (BITCODE_TF)rbuf->value.str.u.data, rbuf->value.str.size);
4636 LOG_TRACE ("xdata[%u]: [TF %d %d] ", j, rbuf->value.str.size,
4637 rbuf->type);
4638 LOG_TRACE_TF (rbuf->value.str.u.data, rbuf->value.str.size);
4639 LOG_POS;
4640 break;
4641 case DWG_VT_HANDLE:
4642 case DWG_VT_OBJECTID:
4643 if (dat->byte + 8 > end)
4644 break;
4645 for (i = 0; i < 8; i++)
4646 bit_write_RC (dat, rbuf->value.hdl[i]);
4647 LOG_TRACE ("xdata[%u]: " FORMAT_H " [H %d]", j,
4648 ARGS_H (rbuf->value.h), rbuf->type);
4649 LOG_POS;
4650 break;
4651 case DWG_VT_INVALID:
4652 default:
4653 LOG_ERROR ("Invalid group code in xdata: %d", rbuf->type);
4654 error = DWG_ERR_INVALIDEED;
4655 break;
4656 }
4657 rbuf = rbuf->nextrb;
4658 j++;
4659 if (j >= _obj->num_xdata)
4660 break;
4661 if (dat->byte >= end)
4662 {
4663 LOG_WARN ("xdata overflow %u", xdata_size);
4664 break;
4665 }
4666 }
4667 if (_obj->xdata_size != dat->byte - start)
4668 {
4669 if (dat->opts & DWG_OPTS_IN) // imprecise xdata_size: calculate
4670 {
4671 _obj->xdata_size = dat->byte - start;
4672 LOG_TRACE ("-xdata_size: " FORMAT_BL " (calculated)\n", _obj->xdata_size);
4673 return error;
4674 }
4675 else
4676 {
4677 LOG_WARN ("xdata Written %lu, expected " FORMAT_BL, dat->byte - start,
4678 _obj->xdata_size);
4679 _obj->xdata_size = dat->byte - start;
4680 return error ? error : 1;
4681 }
4682 }
4683 return 0;
4684 }
4685
4686 #undef IS_ENCODER
4687