1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2018-2021 Free Software Foundation, Inc. */
5 /* */
6 /* This library is free software, licensed under the terms of the GNU */
7 /* General Public License as published by the Free Software Foundation, */
8 /* either version 3 of the License, or (at your option) any later version. */
9 /* You should have received a copy of the GNU General Public License */
10 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
11 /*****************************************************************************/
12
13 /*
14 * in_dxf.c: read ascii DXF
15 * written by Reini Urban
16 */
17
18 #include "config.h"
19 #ifdef __STDC_ALLOC_LIB__
20 # define __STDC_WANT_LIB_EXT2__ 1 /* for strdup */
21 #else
22 # define _USE_BSD 1
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <limits.h>
29 #include <errno.h>
30 //#include <ctype.h>
31 #include <math.h>
32 // strings.h or string.h
33 #ifdef AX_STRCASECMP_HEADER
34 # include AX_STRCASECMP_HEADER
35 #endif
36
37 #define IS_INDXF
38 #include "common.h"
39 #include "importer.h"
40 #include "bits.h"
41 #include "dwg.h"
42 #include "out_dxf.h"
43 #include "decode.h"
44 #include "encode.h"
45 #include "dynapi.h"
46 #include "hash.h"
47 #include "classes.h"
48 #include "free.h"
49
50 static unsigned int loglevel;
51 #define DWG_LOGLEVEL loglevel
52 #include "logging.h"
53
54 #include "in_dxf.h"
55
56 #ifndef _DWG_API_H_
57 Dwg_Object *dwg_obj_generic_to_object (const void *restrict obj,
58 int *restrict error);
59 #endif
60 // from dwg.c
61 BITCODE_H
62 dwg_find_tablehandle_silent (Dwg_Data *restrict dwg, const char *restrict name,
63 const char *restrict table);
64
65 /* the current version per spec block */
66 static unsigned int cur_ver = 0;
67 static char buf[4096];
68 static long start, end; // stream offsets
69 static array_hdls *header_hdls = NULL;
70 static array_hdls *eed_hdls = NULL;
71 static array_hdls *obj_hdls = NULL;
72
73 //static long num_dxf_objs; // how many elements are added
74 //static long size_dxf_objs; // how many elements are allocated
75 //static Dxf_Objs *dxf_objs;
76
77 #define EXPECT_DXF(nam, field, dxf) \
78 if (pair == NULL || pair->code != dxf) \
79 { \
80 LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s", nam, \
81 pair ? pair->code : -1, dxf, #field); \
82 return pair; \
83 }
84 #define EXPECT_INT_DXF(field, dxf, type) \
85 EXPECT_DXF (obj->name, #field, dxf); \
86 dwg_dynapi_entity_set_value (o, obj->name, field, &pair->value, 1); \
87 LOG_TRACE ("%s.%s = %d [" #type " %d]\n", obj->name, field, pair->value.i, \
88 pair->code); \
89 dxf_free_pair (pair)
90 #define EXPECT_DBL_DXF(field, dxf, type) \
91 EXPECT_DXF (obj->name, #field, dxf); \
92 dwg_dynapi_entity_set_value (o, obj->name, field, &pair->value, 1); \
93 LOG_TRACE ("%s.%s = %f [" #type " %d]\n", obj->name, field, pair->value.d, \
94 pair->code); \
95 dxf_free_pair (pair)
96 #define EXPECT_H_DXF(field, htype, dxf, type) \
97 EXPECT_DXF (obj->name, #field, dxf); \
98 if (pair->value.u) \
99 { \
100 BITCODE_H hdl = dwg_add_handleref (dwg, htype, pair->value.u, obj); \
101 dwg_dynapi_entity_set_value (o, obj->name, field, &hdl, 1); \
102 LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n", obj->name, field, \
103 ARGS_REF (hdl), pair->code); \
104 } \
105 dxf_free_pair (pair)
106 #define EXPECT_T_DXF(field, dxf) \
107 EXPECT_DXF (obj->name, #field, dxf); \
108 if (pair->value.s) \
109 { \
110 dwg_dynapi_entity_set_value (o, obj->name, field, &pair->value.s, 1); \
111 LOG_TRACE ("%s.%s = \"%s\" [T %d]\n", obj->name, field, pair->value.s, \
112 pair->code); \
113 } \
114 dxf_free_pair (pair)
115
116 // stricter ordering for special subclasses:
117 #define FIELD_B(field, dxf) \
118 if (dxf) \
119 { \
120 pair = dxf_read_pair (dat); \
121 EXPECT_INT_DXF (#field, dxf, B); \
122 }
123 #define FIELD_RC(field, dxf) \
124 if (dxf) \
125 { \
126 pair = dxf_read_pair (dat); \
127 EXPECT_INT_DXF (#field, dxf, RC); \
128 }
129 #define FIELD_BS(field, dxf) \
130 if (dxf) \
131 { \
132 pair = dxf_read_pair (dat); \
133 EXPECT_INT_DXF (#field, dxf, BS); \
134 }
135 #define FIELD_BLd(field, dxf) \
136 if (dxf) \
137 { \
138 pair = dxf_read_pair (dat); \
139 EXPECT_INT_DXF (#field, dxf, BLd); \
140 }
141 #define FIELD_BL(field, dxf) \
142 if (dxf) \
143 { \
144 pair = dxf_read_pair (dat); \
145 EXPECT_INT_DXF (#field, dxf, BL); \
146 }
147 #define FIELD_BD(field, dxf) \
148 if (dxf) \
149 { \
150 pair = dxf_read_pair (dat); \
151 EXPECT_DBL_DXF (#field, dxf, BD); \
152 }
153 #define FIELD_3BD(field, dxf) \
154 if (dxf) \
155 { \
156 BITCODE_3BD pt; \
157 pair = dxf_read_pair (dat); \
158 EXPECT_DXF (obj->name, #field, dxf); \
159 pt.x = pair->value.d; \
160 dxf_free_pair (pair); \
161 \
162 pair = dxf_read_pair (dat); \
163 EXPECT_DXF (obj->name, #field, dxf + 10); \
164 pt.y = pair->value.d; \
165 dxf_free_pair (pair); \
166 \
167 pair = dxf_read_pair (dat); \
168 EXPECT_DXF (obj->name, #field, dxf + 20); \
169 pt.z = pair->value.d; \
170 dwg_dynapi_entity_set_value (o, obj->name, #field, &pt, 1); \
171 LOG_TRACE ("%s.%s = (%f, %f, %f) [3BD %d]\n", obj->name, #field, pt.x, \
172 pt.y, pt.z, pair->code - 20); \
173 dxf_free_pair (pair); \
174 }
175 #define FIELD_3BD_1(field, dxf) \
176 if (dxf) \
177 { \
178 BITCODE_3BD pt; \
179 pair = dxf_read_pair (dat); \
180 EXPECT_DXF (obj->name, #field, dxf); \
181 pt.x = pair->value.d; \
182 dxf_free_pair (pair); \
183 \
184 pair = dxf_read_pair (dat); \
185 EXPECT_DXF (obj->name, #field, dxf + 1); \
186 pt.y = pair->value.d; \
187 dxf_free_pair (pair); \
188 \
189 pair = dxf_read_pair (dat); \
190 EXPECT_DXF (obj->name, #field, dxf + 2); \
191 pt.z = pair->value.d; \
192 dwg_dynapi_entity_set_value (o, obj->name, #field, &pt, 1); \
193 LOG_TRACE ("%s.%s = (%f, %f, %f) [3BD_1 %d]\n", obj->name, #field, pt.x,\
194 pt.y, pt.z, pair->code - 2); \
195 dxf_free_pair (pair); \
196 }
197 #define FIELD_HANDLE(field, code, dxf) \
198 if (dxf) \
199 { \
200 pair = dxf_read_pair (dat); \
201 EXPECT_H_DXF (#field, code, dxf, H); \
202 }
203 #define FIELD_T(field, dxf) \
204 if (dxf) \
205 { \
206 pair = dxf_read_pair (dat); \
207 EXPECT_T_DXF (#field, dxf); \
208 }
209
210 static void *
xcalloc(size_t n,size_t s)211 xcalloc (size_t n, size_t s)
212 {
213 void *p;
214 if ((n * s) > INT32_MAX)
215 goto err;
216 p = calloc (n, s);
217 if (!p)
218 {
219 err:
220 LOG_ERROR ("Out of memory with calloc %ld * %ld\n", (long)n, (long)s);
221 return NULL;
222 }
223 return p;
224 }
225
226 static inline void
dxf_skip_ws(Bit_Chain * dat)227 dxf_skip_ws (Bit_Chain *dat)
228 {
229 const int is_binary = dat->opts & DWG_OPTS_DXFB;
230 if (is_binary)
231 return;
232 if (dat->byte >= dat->size)
233 return;
234 // clang-format off
235 for (; (!dat->chain[dat->byte] ||
236 dat->chain[dat->byte] == ' ' ||
237 dat->chain[dat->byte] == '\t' ||
238 dat->chain[dat->byte] == '\r');
239 )
240 // clang-format on
241 {
242 dat->byte++;
243 if (dat->byte >= dat->size)
244 return;
245 }
246 }
247
248 #define SAFER_STRTOL(num, rettype, ret) \
249 if (dat->byte + 3 >= dat->size \
250 || !memchr (&dat->chain[dat->byte], '\n', dat->size - dat->byte)) \
251 { \
252 LOG_ERROR ("Premature DXF end"); \
253 dat->byte = dat->size; \
254 return (rettype)ret; \
255 } \
256 errno = 0; \
257 num = strtol ((char *)&dat->chain[dat->byte], &endptr, 10); \
258 if (endptr) \
259 { \
260 if (endptr == (char *)&dat->chain[dat->byte]) \
261 { \
262 LOG_ERROR ("Expected DXF integer value"); \
263 dat->byte = dat->size; \
264 return (rettype)ret; \
265 } \
266 dat->byte += (unsigned char *)endptr - &dat->chain[dat->byte]; \
267 } \
268 if (errno == ERANGE) \
269 return (rettype)num; \
270 if (dat->byte + 1 >= dat->size) \
271 return (rettype)num
272
273 static BITCODE_RC
dxf_read_rc(Bit_Chain * dat)274 dxf_read_rc (Bit_Chain *dat)
275 {
276 const int is_binary = dat->opts & DWG_OPTS_DXFB;
277 if (is_binary)
278 {
279 return bit_read_RC (dat);
280 }
281 else
282 {
283 char *endptr;
284 long num;
285 // avoid overflow over dat->size
286 SAFER_STRTOL (num, BITCODE_RC, 0);
287 if (dat->chain[dat->byte] == '\r')
288 dat->byte++;
289 if (dat->chain[dat->byte] == '\n')
290 dat->byte++;
291 if (num > 65534)
292 LOG_ERROR ("%s: RC overflow %ld (at %lu)", __FUNCTION__, num,
293 dat->byte);
294 return (BITCODE_RC)num;
295 }
296 }
297
298 static BITCODE_RS
dxf_read_rs(Bit_Chain * dat)299 dxf_read_rs (Bit_Chain *dat)
300 {
301 const int is_binary = dat->opts & DWG_OPTS_DXFB;
302 if (is_binary)
303 {
304 return bit_read_RS (dat);
305 }
306 else
307 {
308 char *endptr;
309 long num;
310 SAFER_STRTOL (num, BITCODE_RS, 0);
311 if (dat->chain[dat->byte] == '\r')
312 dat->byte++;
313 if (dat->chain[dat->byte] == '\n')
314 dat->byte++;
315 if (num > 65534)
316 LOG_ERROR ("%s: RS overflow %ld (at %lu)", __FUNCTION__, num,
317 dat->byte);
318 return (BITCODE_RS)num;
319 }
320 }
321
322 static BITCODE_RL
dxf_read_rl(Bit_Chain * dat)323 dxf_read_rl (Bit_Chain *dat)
324 {
325 const int is_binary = dat->opts & DWG_OPTS_DXFB;
326 if (is_binary)
327 {
328 return bit_read_RL (dat);
329 }
330 else
331 {
332 char *endptr;
333 long num;
334 // avoid overflow over dat->size
335 SAFER_STRTOL (num, BITCODE_RL, 0);
336 if (dat->chain[dat->byte] == '\r')
337 dat->byte++;
338 if (dat->chain[dat->byte] == '\n')
339 dat->byte++;
340 if (num > INT_MAX)
341 LOG_ERROR ("%s: RL overflow %ld (at %lu)", __FUNCTION__, num,
342 dat->byte);
343 return (BITCODE_RL)num;
344 }
345 }
346
347 static BITCODE_RLL
dxf_read_rll(Bit_Chain * dat)348 dxf_read_rll (Bit_Chain *dat)
349 {
350 const int is_binary = dat->opts & DWG_OPTS_DXFB;
351 if (is_binary)
352 {
353 return bit_read_RLL (dat);
354 }
355 else
356 {
357 char *endptr;
358 BITCODE_RLL num;
359 // avoid overflow over dat->size (need final " 0\nEOF")
360 SAFER_STRTOL (num, BITCODE_RLL, 0UL);
361 if (dat->chain[dat->byte] == '\r')
362 dat->byte++;
363 if (dat->chain[dat->byte] == '\n')
364 dat->byte++;
365 if ((unsigned long)num > LONG_MAX) // or wrap to negative
366 LOG_ERROR ("%s: long overflow %ld (at %lu)", __FUNCTION__, (long)num,
367 dat->byte);
368 return num;
369 }
370 }
371
372 static BITCODE_RD
dxf_read_rd(Bit_Chain * dat)373 dxf_read_rd (Bit_Chain *dat)
374 {
375 const int is_binary = dat->opts & DWG_OPTS_DXFB;
376 if (is_binary)
377 {
378 return bit_read_RD (dat);
379 }
380 else
381 {
382 char *str, *endptr;
383 BITCODE_RD num;
384 dxf_skip_ws (dat);
385 str = (char *)&dat->chain[dat->byte];
386 // avoid overflow over dat->size
387 if (dat->byte + 6 >= dat->size || !memchr (str, '\n', dat->size - dat->byte - 6))
388 {
389 LOG_ERROR ("Premature DXF end");
390 dat->byte = dat->size;
391 return (double)NAN;
392 }
393 else
394 num = strtod (str, &endptr);
395 if (endptr)
396 dat->byte += endptr - str;
397 if (errno == ERANGE)
398 return (double)NAN;
399 return num;
400 }
401 }
402
403 #if 0
404 // not yet needed. only with write2004
405 // ASCII: series of 310 HEX encoded
406 // BINARY: ??
407 static unsigned char *
408 dxf_read_binary (Bit_Chain *dat, unsigned char **p, int len)
409 {
410 unsigned char *data;
411 const char *pos = (char*)&dat->chain[dat->byte];
412 const int is_binary = dat->opts & DWG_OPTS_DXFB;
413 const unsigned size = len / 2;
414 unsigned read;
415 if (dat->byte + size >= dat->size)
416 return NULL;
417 //if (is_binary)
418 data = p && *p ? (unsigned char *)realloc (*p, size) : (unsigned char *)malloc (size);
419 if (!data)
420 {
421 LOG_ERROR ("Out of memory");
422 return NULL;
423 }
424 LOG_TRACE ("binary[%u]: ", size);
425 if ((read = in_hex2bin (data, pos, size) != size))
426 LOG_ERROR ("in_hex2bin read only %u of %u", read, size);
427 dat->byte += read;
428 if (p)
429 *p = data;
430 return data;
431 }
432 #endif
433
434 // Unicode strings are UTF-8 with quoted \\U+
435 // BINARY: no length prefixes, just zero-terminated strings
436 static void
dxf_read_string(Bit_Chain * dat,char ** string)437 dxf_read_string (Bit_Chain *dat, char **string)
438 {
439 const int is_binary = dat->opts & DWG_OPTS_DXFB;
440 if (dat->byte >= dat->size)
441 return;
442 if (is_binary)
443 {
444 #if 1
445 int size = strlen ((char*)&dat->chain[dat->byte]) + 1;
446 if (!string)
447 {
448 strncpy (buf, (char*)&dat->chain[dat->byte], 4096);
449 if (size > 4095)
450 buf[4095] = '\0';
451 }
452 else
453 {
454 *string = !*string ? (char *)malloc (size) : (char *)realloc (*string, size);
455 strcpy (*string, (char*)&dat->chain[dat->byte]);
456 }
457 dat->byte += size;
458 #else
459 int size = sscanf ((char*)&dat->chain[dat->byte], "%s", (char*)buf);
460 buf[4095] = '\0';
461 if (size != EOF)
462 size = strlen (buf) + 1;
463 dat->byte += size;
464 if (!string)
465 {
466 if (size > 4096)
467 return;
468 return; // ignore, just advanced dat
469 }
470 *string = !*string ? (char *)malloc (size) : (char *)realloc (*string, size);
471 strcpy (*string, buf);
472 #endif
473 }
474 else
475 {
476 int i;
477 dxf_skip_ws (dat);
478 if (dat->byte >= dat->size || !memchr (&dat->chain[dat->byte], '\n', dat->size - dat->byte))
479 return;
480 for (i = 0;
481 dat->byte < dat->size && dat->chain[dat->byte] != '\n' && i < 4096;
482 dat->byte++)
483 {
484 buf[i++] = dat->chain[dat->byte];
485 }
486 if (dat->byte >= dat->size || i >= 4096)
487 return;
488 if (i && buf[i - 1] == '\r')
489 buf[i - 1] = '\0';
490 else
491 buf[i] = '\0';
492 dat->byte++;
493
494 // dxf_skip_ws (dat);
495 if (!string)
496 return; // ignore, just advanced dat
497 if (!*string)
498 *string = (char *)malloc (strlen (buf) + 1);
499 else
500 *string = (char *)realloc (*string, strlen (buf) + 1);
501 strcpy (*string, buf);
502 }
503 }
504
505 static void
dxf_free_pair(Dxf_Pair * pair)506 dxf_free_pair (Dxf_Pair *pair)
507 {
508 if (!pair)
509 return;
510 if (pair->type == DWG_VT_STRING || pair->type == DWG_VT_BINARY)
511 {
512 free (pair->value.s);
513 pair->value.s = NULL;
514 }
515 else if (pair->code == 0 || pair->code == 2)
516 {
517 free (pair->value.s);
518 pair->value.s = NULL;
519 }
520 free (pair);
521 pair = NULL;
522 }
523
524 static Dxf_Pair *ATTRIBUTE_MALLOC
dxf_read_pair(Bit_Chain * dat)525 dxf_read_pair (Bit_Chain *dat)
526 {
527 Dxf_Pair *pair = (Dxf_Pair *)xcalloc (1, sizeof (Dxf_Pair));
528 const int is_binary = dat->opts & DWG_OPTS_DXFB;
529 if (!pair)
530 return NULL;
531 if (dat->size - dat->byte < 6) // at least 0\nEOF\n
532 {
533 err:
534 LOG_ERROR ("Unexpected DXF end-of-file");
535 free (pair);
536 return NULL;
537 }
538 if (is_binary)
539 LOG_HANDLE ("%4lx: ", dat->byte);
540 pair->code = (short)dxf_read_rs (dat);
541 if (dat->size - dat->byte < 4) // at least EOF\n
542 goto err;
543 pair->type = dwg_resbuf_value_type (pair->code);
544 //if (pair->code == 280) // && strEQc (key, "ENDCAPS")
545 // pair->type = DWG_VT_INT16; // for HEADER.ENDCAPS - CEPSNTYPE
546 switch (pair->type)
547 {
548 case DWG_VT_STRING:
549 dxf_read_string (dat, &pair->value.s);
550 if (!pair->value.s && pair->code != 0)
551 pair->value.s = calloc(1, 1);
552 LOG_TRACE (" dxf (%d, \"%s\")\n", (int)pair->code, pair->value.s);
553 // dynapi_set_helper converts from utf-8 to unicode, not here.
554 // we need to know the type of the target field, if TV or T
555 break;
556 case DWG_VT_BOOL:
557 case DWG_VT_INT8:
558 pair->value.i = dxf_read_rc (dat);
559 LOG_TRACE (" dxf (%d, %d)\n", (int)pair->code, pair->value.i);
560 break;
561 case DWG_VT_INT16:
562 pair->value.i = dxf_read_rs (dat);
563 LOG_TRACE (" dxf (%d, %d)\n", (int)pair->code, pair->value.i);
564 break;
565 case DWG_VT_INT32:
566 pair->value.l = dxf_read_rl (dat);
567 LOG_TRACE (" dxf (%d, %ld)\n", (int)pair->code, pair->value.l);
568 break;
569 case DWG_VT_INT64:
570 pair->value.rll = dxf_read_rll (dat);
571 LOG_TRACE (" dxf (%d, " FORMAT_RLL ")\n", (int)pair->code,
572 pair->value.rll);
573 break;
574 case DWG_VT_REAL:
575 case DWG_VT_POINT3D:
576 dxf_skip_ws (dat);
577 pair->value.d = dxf_read_rd (dat);
578 LOG_TRACE (" dxf (%d, %f)\n", pair->code, pair->value.d);
579 break;
580 case DWG_VT_BINARY:
581 // zero-terminated. TODO hex decode here already?
582 dxf_read_string (dat, &pair->value.s);
583 if (!pair->value.s)
584 pair->value.s = calloc(1, 1);
585 LOG_TRACE (" dxf (%d, %s)\n", (int)pair->code, pair->value.s);
586 break;
587 case DWG_VT_HANDLE:
588 case DWG_VT_OBJECTID:
589 // BINARY: hex string without len
590 dxf_read_string (dat, NULL);
591 sscanf (buf, "%X", &pair->value.u);
592 LOG_TRACE (" dxf (%d, %X)\n", (int)pair->code, pair->value.u);
593 break;
594 case DWG_VT_INVALID:
595 default:
596 LOG_ERROR ("Invalid DXF group code: %d", pair->code);
597 dxf_free_pair (pair);
598 return NULL;
599 }
600 return pair;
601 }
602
603 #define DXF_CHECK_EOF \
604 if (dat->byte >= dat->size || (pair == NULL) \
605 || (pair->code == 0 && !pair->value.s) \
606 || (pair->code == 0 && strEQc (pair->value.s, "EOF"))) \
607 { \
608 if (pair) \
609 dxf_free_pair (pair); \
610 pair = NULL; \
611 return 1; \
612 }
613 #define DXF_RETURN_EOF(what) \
614 if (dat->byte >= dat->size || (pair == NULL) \
615 || (pair->code == 0 && !pair->value.s) \
616 || (pair->code == 0 && strEQc (pair->value.s, "EOF"))) \
617 { \
618 if (pair) \
619 dxf_free_pair (pair); \
620 pair = NULL; \
621 return what; \
622 }
623 #define DXF_BREAK_EOF \
624 if (dat->byte >= dat->size || (pair == NULL) \
625 || (pair->code == 0 && !pair->value.s) \
626 || (pair->code == 0 && strEQc (pair->value.s, "EOF"))) \
627 break
628
629 static Dxf_Pair *
dxf_skip_comment(Bit_Chain * dat,Dxf_Pair * pair)630 dxf_skip_comment (Bit_Chain *dat, Dxf_Pair *pair)
631 {
632 while (pair != NULL && pair->code == 999)
633 {
634 dxf_free_pair (pair);
635 pair = dxf_read_pair (dat);
636 DXF_RETURN_EOF (pair);
637 }
638 return pair;
639 }
640
641 /* destlen = strlen(src) / 2;
642 if ((written = in_hex2bin (malloc (destlen), src, destlen)) != destlen)
643 error
644
645 TODO: optimize for the typical line len 254 (destlen 127)
646
647 benchmarks:
648 checked hex2bin: 0.624826 sec (if < >)...
649 sscanf hex2bin: 20.150780 sec
650 lookup2 hex2bin: 0.162167 sec (124x faster)
651 */
in_hex2bin(unsigned char * restrict dest,char * restrict src,unsigned destlen)652 unsigned in_hex2bin (unsigned char *restrict dest, char *restrict src, unsigned destlen)
653 {
654 #if 0
655 char *pos = (char *)src;
656 for (unsigned i = 0; i < destlen; i++)
657 {
658 if (sscanf (pos, SCANF_2X, &dest[i]))
659 pos += 2;
660 else
661 return i;
662 }
663 return destlen;
664 #else
665 char *pos = (char *)src;
666 // 124x faster, but no error checks.
667 // src must consist of valid uppercase hex chars only
668 static const unsigned char h2b_lookup[] = {
669 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
670 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
671 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ...
673 };
674 const char *_end = pos + (destlen << 1);
675 /* slower
676 const char *_end4 = pos + ((destlen << 1) & ~0x3);
677 const int64_t magic = INT64_C(0x1001001000000000);
678 uint32_t *d32 = (uint32_t*)dest;
679 while (pos < _end4) {
680 uint32_t in;
681 uint64_t v, x;
682 memcpy (&in, pos, 4);
683 v = in;
684 x = (((0x00404040 & v) >> 6) * 9) + (v & 0x000F0F0F); // do 3
685 x = (((uint64_t)((int64_t)x * magic)) >> 48) & ~15; // bswap and pack
686 v = ((v >> 30) * 9) + ((v >> 24) & 0x0F); // do the 4th
687 *d32++ = (x | v);
688 pos += 4;
689 }*/
690 while (pos < _end) {
691 unsigned char v1 = h2b_lookup[(pos[0] & 0x1F) ^ 0x10];
692 unsigned char v2 = h2b_lookup[(pos[1] & 0x1F) ^ 0x10];
693 *dest++ = (v1 << 4 | v2);
694 pos += 2;
695 }
696 return destlen;
697 #endif
698 }
699
700 /*--------------------------------------------------------------------------------
701 * MACROS
702 */
703
704 #define ACTION indxf
705 //#define IS_ENCODER
706 //#define IS_DXF
707
708 /* Store all handle fieldnames and string values into this flexarray.
709 We need strdup'd copies, the dxf input will be freed.
710 */
711 array_hdls *
array_push(array_hdls * restrict hdls,const char * restrict field,const char * restrict name,const int code)712 array_push (array_hdls *restrict hdls, const char *restrict field,
713 const char *restrict name, const int code)
714 {
715 uint32_t i = hdls->nitems;
716 if (i >= hdls->size)
717 {
718 hdls->size += 16;
719 hdls = (array_hdls *)realloc (
720 hdls, 8 + (hdls->size * sizeof (struct array_hdl)));
721 if (!hdls)
722 {
723 LOG_ERROR ("Out of memory");
724 return NULL;
725 }
726 // memset (hdls, 0, 8 + (hdls->size * sizeof (struct array_hdl));
727 }
728 hdls->nitems = i + 1;
729 hdls->items[i].field = strdup (field);
730 hdls->items[i].name = strdup (name);
731 hdls->items[i].code = code;
732 return hdls;
733 }
734
735 array_hdls *
new_array_hdls(int size)736 new_array_hdls (int size)
737 {
738 array_hdls *hdls
739 = (array_hdls *)xcalloc (1, 8 + size * sizeof (struct array_hdl));
740 if (!hdls)
741 return NULL;
742 hdls->size = size;
743 return hdls;
744 }
745
746 void
free_array_hdls(array_hdls * hdls)747 free_array_hdls (array_hdls *hdls)
748 {
749 for (uint32_t i = 0; i < hdls->nitems; i++)
750 {
751 free (hdls->items[i].field);
752 free (hdls->items[i].name);
753 }
754 free (hdls);
755 }
756
757 #define DXF_CHECK_ENDSEC \
758 if (pair != NULL \
759 && (dat->byte >= dat->size || (pair->code == 0 && !pair->value.s) \
760 || (pair->code == 0 && strEQc (pair->value.s, "ENDSEC")))) \
761 return 0
762 #define DXF_BREAK_ENDSEC \
763 if (pair != NULL \
764 && (dat->byte >= dat->size || (pair->code == 0 && !pair->value.s) \
765 || (pair->code == 0 && strEQc (pair->value.s, "ENDSEC")))) \
766 break
767 #define DXF_RETURN_ENDSEC(what) \
768 if (pair != NULL \
769 && (dat->byte >= dat->size || (pair->code == 0 && !pair->value.s) \
770 || (pair->code == 0 && strEQc (pair->value.s, "ENDSEC")))) \
771 { \
772 dxf_free_pair (pair); \
773 return what; \
774 }
775
776 static Dxf_Pair *
dxf_expect_code(Bit_Chain * restrict dat,Dxf_Pair * restrict pair,int code)777 dxf_expect_code (Bit_Chain *restrict dat, Dxf_Pair *restrict pair, int code)
778 {
779 while (pair != NULL && pair->code != code)
780 {
781 dxf_free_pair (pair);
782 pair = dxf_read_pair (dat);
783 pair = dxf_skip_comment (dat, pair);
784 DXF_RETURN_EOF (pair);
785 if (pair && pair->code != code)
786 {
787 LOG_ERROR ("Expecting DXF code %d, got %d (at %lu)", code,
788 pair->code, dat->byte);
789 }
790 }
791 return pair;
792 }
793
794 static int
matches_type(Dxf_Pair * restrict pair,const Dwg_DYNAPI_field * restrict f)795 matches_type (Dxf_Pair *restrict pair, const Dwg_DYNAPI_field *restrict f)
796 {
797 switch (pair->type)
798 {
799 case DWG_VT_STRING:
800 if (f->is_string)
801 return 1;
802 if (f->type[0] == 'H')
803 return 1; // handles can be just names
804 break;
805 case DWG_VT_INT64:
806 // BLL or RLL
807 if (f->size == 8 && f->type[1] == 'L' && f->type[2] == 'L')
808 return 1;
809 // fall through
810 case DWG_VT_INT32:
811 // BL or RL
812 if (f->size == 4 && f->type[1] == 'L')
813 return 1;
814 // fall through
815 case DWG_VT_INT16:
816 // BS or RS or CMC
817 if (f->size == 2 && f->type[1] == 'S')
818 return 1;
819 if (strEQc (f->type, "CMC"))
820 return 1;
821 if (strEQc (f->type, "BSd"))
822 return 1;
823 // fall through
824 case DWG_VT_INT8:
825 if (strEQc (f->type, "RC"))
826 return 1;
827 // fall through
828 case DWG_VT_BOOL:
829 if (strEQc (f->type, "B"))
830 return 1;
831 break;
832 case DWG_VT_REAL:
833 // BD or RD
834 if (f->size == 8 && f->type[1] == 'D')
835 return 1;
836 if (strEQc (f->type, "TIMEBLL"))
837 return 1;
838 break;
839 case DWG_VT_POINT3D:
840 // 3BD or 3RD or 3DPOINT or BE
841 if (f->size == 24 && (f->type[0] == '3' || strEQc (f->type, "BE")))
842 return 1;
843 // accept 2BD or 2RD or 2DPOINT also
844 if (f->size == 16 && f->type[0] == '2')
845 return 1;
846 break;
847 case DWG_VT_BINARY:
848 if (f->is_string)
849 return 1;
850 break;
851 case DWG_VT_HANDLE:
852 case DWG_VT_OBJECTID:
853 if (f->type[0] == 'H')
854 return 1;
855 break;
856 case DWG_VT_INVALID:
857 default:
858 LOG_ERROR ("Invalid DXF group code: %d", pair->code);
859 }
860 return 0;
861 }
862
863 /* Also used by in_json */
864 const Dwg_DYNAPI_field *
find_numfield(const Dwg_DYNAPI_field * restrict fields,const char * restrict key)865 find_numfield (const Dwg_DYNAPI_field *restrict fields,
866 const char *restrict key)
867 {
868 const Dwg_DYNAPI_field *f;
869 char s[80];
870 strcpy (s, "num_");
871 strcat (s, key);
872 // see gen-dynapi.pl:1102
873 if (strEQc (key, "attribs"))
874 strcpy (s, "num_owned");
875 else if (strEQc (key, "attribs"))
876 strcpy (s, "num_owned");
877 else if (strEQc (key, "items"))
878 strcpy (s, "numitems");
879 else if (strEQc (key, "entities"))
880 strcpy (s, "num_owned");
881 else if (strEQc (key, "sort_ents"))
882 strcpy (s, "num_ents");
883 else if (strEQc (key, "attr_def_id"))
884 strcpy (s, "num_attr_defs");
885 else if (strEQc (key, "layer_entries"))
886 strcpy (s, "num_entries");
887 else if (strEQc (key, "readdeps"))
888 strcpy (s, "num_deps");
889 else if (strEQc (key, "writedeps"))
890 strcpy (s, "num_deps");
891 else if (strEQc (key, "encr_sat_data"))
892 strcpy (s, "num_blocks");
893 else if (strEQc (key, "styles")) // conflicts? only for LTYPE
894 strcpy (s, "num_dashes");
895 else if (strEQc (key, "cellstyle.borders"))
896 strcpy (s, "cellstyle.num_borders");
897 else if (strEQc (key, "segs") || strEQc (key, "polyline_paths"))
898 strcpy (s, "num_segs_or_paths");
899 else if (strEQc (key, "txt.col_sizes"))
900 strcpy (s, "txt.num_col_sizes");
901 search:
902 for (f = &fields[0]; f->name; f++)
903 {
904 if (strEQ (s, f->name))
905 return f;
906 }
907 // or num_owner
908 if (strEQc (key, "vertex"))
909 {
910 strcpy (s, "num_owned");
911 goto search;
912 }
913 // there are two of them
914 if (strEQc (key, "paths") && strNE (s, "num_segs_or_paths"))
915 {
916 strcpy (s, "num_segs_or_paths");
917 goto search;
918 }
919 return NULL;
920 }
921
922 /* convert to flag */
923 BITCODE_RC
dxf_find_lweight(const int lw)924 dxf_find_lweight (const int lw)
925 {
926 // See acdb.h: 100th of a mm, enum of
927 const int lweights[] = { 0,
928 5,
929 9,
930 13,
931 15,
932 18,
933 20,
934 25,
935 30,
936 35,
937 40,
938 50,
939 53,
940 60,
941 70,
942 80,
943 90,
944 100,
945 106,
946 120,
947 140,
948 158,
949 200,
950 211,
951 /*illegal/reserved:*/ 0,
952 0,
953 0,
954 0,
955 0,
956 /*29:*/ -1, // BYLAYER
957 -2, // BYBLOCK
958 -3 }; // BYLWDEFAULT
959 for (int i = 0; i < 32; i++)
960 {
961 if (lweights[i] == lw)
962 return i;
963 }
964 return 0;
965 }
966
967 // FIXME: support 430 (name), 440 (alpha)
968 static int
dxf_read_CMC(const Dwg_Data * restrict dwg,Bit_Chain * restrict dat,BITCODE_CMC * restrict color,const char * fieldname,const int dxf)969 dxf_read_CMC (const Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
970 BITCODE_CMC *restrict color, const char *fieldname, const int dxf)
971 {
972 int error = 1;
973 unsigned long pos = bit_position (dat);
974 Dxf_Pair *pair = dxf_read_pair (dat);
975 if (!color)
976 {
977 LOG_ERROR ("empty CMC field %s", fieldname);
978 return 1;
979 }
980 if (pair->code < 90 && dxf == pair->code)
981 {
982 color->index = pair->value.i;
983 if (pair->value.i == 256) // bylayer
984 color->method = 0xc2;
985 if (pair->value.i == 257) // none
986 color->method = 0xc8;
987 else if (dwg->header.version >= R_2004)
988 {
989 color->index = 256;
990 color->rgb = pair->value.l;
991 color->rgb |= 0xc2000000;
992 LOG_TRACE ("%s.rgb = 0x%08x [%s %d]\n", fieldname, color->rgb, "CMC",
993 pair->code);
994 }
995 LOG_TRACE ("%s.index = %d [%s %d]\n", fieldname, color->index, "CMC",
996 pair->code);
997 // optional 420, 430, 440 fields
998 pos = bit_position (dat);
999 error = dxf_read_CMC (dwg, dat, color, fieldname, dxf);
1000 }
1001 else if (pair->code < 430 && pair->code == (dxf + 420 - 62)) // truecolor
1002 {
1003 color->rgb = pair->value.l;
1004 color->rgb |= 0xc3000000;
1005 LOG_TRACE ("%s.rgb = 0x%08x [%s %d]\n", fieldname, color->rgb, "CMC",
1006 pair->code);
1007 error = 0;
1008 }
1009 // TODO 430, 440
1010 else if (pair->code < 440 && pair->code == (dxf + 430 - 62)) // name
1011 {
1012 LOG_WARN ("%s.name %s ignored [%s %d]", fieldname, pair->value.s, "CMC",
1013 pair->code);
1014 error = 0;
1015 }
1016 else if (pair->code < 450 && pair->code == (dxf + 440 - 62)) // alpha
1017 {
1018 LOG_WARN ("%s.alpha %ld ignored [%s %d]", fieldname, pair->value.l, "CMC",
1019 pair->code);
1020 error = 0;
1021 }
1022 dxf_free_pair (pair);
1023 if (error)
1024 {
1025 LOG_TRACE ("no optional CMC, backup\n");
1026 bit_set_position (dat, pos);
1027 }
1028 return error;
1029 }
1030
1031 static int
dxf_header_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1032 dxf_header_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1033 {
1034 Dwg_Header_Variables *_obj = &dwg->header_vars;
1035 Dwg_Object *obj = NULL;
1036 const int is_binary = dat->opts & DWG_OPTS_DXFB;
1037 // const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
1038 int is_tu = 1;
1039 int i = 0;
1040 Dxf_Pair *pair;
1041
1042 // defaults, not often found in a DXF
1043 _obj->ISOLINES = 4;
1044 _obj->TEXTQLTY = 50;
1045 _obj->FACETRES = 0.5;
1046
1047 // here SECTION (HEADER) was already consumed
1048 // read the first group 9, $field pair
1049 pair = dxf_read_pair (dat);
1050 while (pair != NULL && pair->code == 9 && pair->value.s)
1051 {
1052 char field[80];
1053 strncpy (field, pair->value.s, 79);
1054 field[79] = '\0';
1055 i = 0;
1056
1057 // now read the code, value pair. for points it may be multiple (index i)
1058 dxf_free_pair (pair);
1059 pair = dxf_read_pair (dat);
1060 if (!pair)
1061 {
1062 pair = dxf_read_pair (dat);
1063 if (!pair)
1064 return 1;
1065 }
1066 DXF_BREAK_ENDSEC;
1067 next_hdrvalue:
1068 if (is_binary && pair->code == 280 &&
1069 (strEQc (field, "$ENDCAPS") || strEQc (field, "$JOINSTYLE")))
1070 dat->byte++; // B => RS
1071 if (pair->code == 1 && strEQc (field, "$ACADVER")
1072 && pair->value.s != NULL)
1073 {
1074 int vi; // C++ quirks
1075 // Note: Here version is still R_INVALID, thus pair->value.s
1076 // is never TU.
1077 const char *version = pair->value.s;
1078 for (Dwg_Version_Type v = R_INVALID; v <= R_AFTER;
1079 vi = (int)v, vi++, v = (Dwg_Version_Type)vi)
1080 {
1081 if (strEQ (version, version_codes[v]))
1082 {
1083 dat->from_version = dwg->header.from_version = v;
1084 is_tu = dat->version >= R_2007;
1085 LOG_TRACE ("HEADER.from_version = %s,\tdat->from_version = %s\n",
1086 version_codes[dwg->header.from_version],
1087 version_codes[dat->from_version]);
1088 if (is_tu && dwg->num_objects
1089 && dwg->object[0].fixedtype == DWG_TYPE_BLOCK_HEADER)
1090 {
1091 Dwg_Object_BLOCK_HEADER *o
1092 = dwg->object[0].tio.object->tio.BLOCK_HEADER;
1093 free (o->name);
1094 o->name
1095 = (char *)bit_utf8_to_TU ((char *)"*Model_Space", 0);
1096 }
1097 break;
1098 }
1099 if (v == R_AFTER)
1100 LOG_ERROR ("Invalid HEADER: 9 %s, 1 %s", field, version)
1101 }
1102 // currently we can only encode DWGs to r13-r2000, but DXF's to almost everything.
1103 if (dwg->header.from_version >= R_13 && dwg->header.from_version <= R_2000)
1104 dwg->header.version = dat->version = dwg->header.from_version;
1105 LOG_TRACE ("HEADER.version = %s,\tdat->version = %s\n",
1106 version_codes[dwg->header.version],
1107 version_codes[dat->version]);
1108 }
1109 else if (field[0] == '$')
1110 {
1111 const Dwg_DYNAPI_field *f = dwg_dynapi_header_field (&field[1]);
1112 if (!f)
1113 {
1114 if (pair->code == 40 && strEQc (field, "$3DDWFPREC"))
1115 {
1116 LOG_TRACE ("HEADER.%s [%s %d]\n", &field[1], "BD",
1117 pair->code);
1118 dwg->header_vars._3DDWFPREC = pair->value.d;
1119 }
1120
1121 #define SUMMARY_T(name) \
1122 (pair->code == 1 && strEQc (field, "$" #name) && pair->value.s != NULL) \
1123 { \
1124 LOG_TRACE ("SUMMARY.%s = %s [TU16 1]\n", &field[1], pair->value.s); \
1125 dwg->summaryinfo.name = bit_utf8_to_TU (pair->value.s, 0); \
1126 }
1127
1128 else if
1129 SUMMARY_T (TITLE)
1130 else if
1131 SUMMARY_T (AUTHOR)
1132 else if
1133 SUMMARY_T (SUBJECT)
1134 else if
1135 SUMMARY_T (KEYWORDS)
1136 else if
1137 SUMMARY_T (COMMENTS)
1138 else if
1139 SUMMARY_T (LASTSAVEDBY)
1140 else if (pair->code == 1 && strEQc (field, "$CUSTOMPROPERTYTAG")
1141 && pair->value.s != NULL)
1142 {
1143 BITCODE_BL j = dwg->summaryinfo.num_props;
1144 dwg->summaryinfo.num_props++;
1145 dwg->summaryinfo.props
1146 = (Dwg_SummaryInfo_Property*)realloc (dwg->summaryinfo.props,
1147 (j + 1) * sizeof (Dwg_SummaryInfo_Property));
1148 LOG_TRACE ("SUMMARY.props[%u].tag = %s [TU16 1]\n", j,
1149 pair->value.s);
1150 dwg->summaryinfo.props[j].tag = bit_utf8_to_TU (pair->value.s, 0);
1151 }
1152 else if (pair->code == 1 && strEQc (field, "$CUSTOMPROPERTY")
1153 && pair->value.s != NULL && dwg->summaryinfo.props
1154 && dwg->summaryinfo.num_props > 0)
1155 {
1156 BITCODE_BL j = dwg->summaryinfo.num_props - 1;
1157 LOG_TRACE ("SUMMARY.props[%u].value = %s [TU16 1]\n", j,
1158 pair->value.s);
1159 dwg->summaryinfo.props[j].value = bit_utf8_to_TU (pair->value.s, 0);
1160 }
1161 else
1162 LOG_ERROR ("skipping HEADER: 9 %s, unknown field with code %d",
1163 field, pair->code);
1164 }
1165 else if (!matches_type (pair, f) && strNE (field, "$XCLIPFRAME")
1166 && strNE (field, "$TIMEZONE"))
1167 {
1168 // XCLIPFRAME is 280 RC or 290 B in dynapi.
1169 // TIMEZONE is BLd (signed)
1170 LOG_ERROR (
1171 "skipping HEADER: 9 %s, wrong type code %d <=> field %s",
1172 field, pair->code, f->type);
1173 }
1174 else if (pair->type == DWG_VT_POINT3D)
1175 {
1176 BITCODE_3BD pt = { 0.0, 0.0, 0.0 };
1177 if (i)
1178 dwg_dynapi_header_value (dwg, &field[1], &pt, NULL);
1179 if (i == 0)
1180 pt.x = pair->value.d;
1181 else if (i == 1)
1182 pt.y = pair->value.d;
1183 else if (i == 2)
1184 pt.z = pair->value.d;
1185 if (i > 2)
1186 {
1187 LOG_ERROR ("skipping HEADER: 9 %s, too many point elements",
1188 field);
1189 }
1190 else
1191 {
1192 // yes, set it 2-3 times
1193 LOG_TRACE ("HEADER.%s [%s %d][%d] = %f\n", &field[1],
1194 f->type, pair->code, i, pair->value.d);
1195 dwg_dynapi_header_set_value (dwg, &field[1], &pt, 1);
1196 i++;
1197 }
1198 }
1199 else if (pair->type == DWG_VT_STRING && strEQc (f->type, "H"))
1200 {
1201 char *key, *str;
1202 if (pair->value.s && strlen (pair->value.s))
1203 {
1204 LOG_TRACE ("HEADER.%s %s [%s %d] later\n", &field[1],
1205 pair->value.s, f->type, (int)pair->code);
1206 // name (which table?) => handle
1207 // needs to be postponed, because we don't have the tables
1208 // yet.
1209 header_hdls = array_push (header_hdls, &field[1],
1210 pair->value.s, pair->code);
1211 }
1212 else
1213 {
1214 BITCODE_H hdl = dwg_add_handleref (dwg, 5, 0, NULL);
1215 LOG_TRACE ("HEADER.%s NULL 5 [H %d]\n", &field[1],
1216 pair->code);
1217 dwg_dynapi_header_set_value (dwg, &field[1], &hdl, 1);
1218 }
1219 }
1220 else if (strEQc (f->type, "H"))
1221 {
1222 BITCODE_H hdl;
1223 hdl = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
1224 LOG_TRACE ("HEADER.%s %X [H %d]\n", &field[1], pair->value.u,
1225 pair->code);
1226 dwg_dynapi_header_set_value (dwg, &field[1], &hdl, 1);
1227 }
1228 else if (strEQc (f->type, "CMC"))
1229 {
1230 static BITCODE_CMC color = { 0 };
1231 if (pair->code <= 70)
1232 {
1233 LOG_TRACE ("HEADER.%s.index %d [CMC %d]\n", &field[1],
1234 pair->value.i, pair->code);
1235 color.index = pair->value.i;
1236 dwg_dynapi_header_set_value (dwg, &field[1], &color, 0);
1237 }
1238 }
1239 else if (pair->type == DWG_VT_REAL && strEQc (f->type, "TIMEBLL"))
1240 {
1241 static BITCODE_TIMEBLL date = { 0, 0, 0 };
1242 date.value = pair->value.d;
1243 date.days = (BITCODE_BL)trunc (pair->value.d);
1244 date.ms = (BITCODE_BL) (86400000.0 * (date.value - date.days));
1245 LOG_TRACE ("HEADER.%s %.09f (" FORMAT_BL ", " FORMAT_BL
1246 ") [TIMEBLL %d]\n",
1247 &field[1], date.value, date.days, date.ms,
1248 pair->code);
1249 dwg_dynapi_header_set_value (dwg, &field[1], &date, 0);
1250 }
1251 else if (pair->type == DWG_VT_STRING)
1252 {
1253 LOG_TRACE ("HEADER.%s [%s %d]\n", &field[1], f->type,
1254 pair->code);
1255 dwg_dynapi_header_set_value (dwg, &field[1], &pair->value, 1);
1256 }
1257 else
1258 {
1259 LOG_TRACE ("HEADER.%s [%s %d]\n", &field[1], f->type,
1260 pair->code);
1261 dwg_dynapi_header_set_value (dwg, &field[1], &pair->value, 1);
1262 }
1263 }
1264 else
1265 {
1266 LOG_ERROR ("skipping HEADER: 9 %s, missing the $", field);
1267 }
1268
1269 dxf_free_pair (pair);
1270 pair = dxf_read_pair (dat);
1271 if (!pair)
1272 {
1273 pair = dxf_read_pair (dat);
1274 if (!pair)
1275 return 1;
1276 }
1277 DXF_BREAK_ENDSEC;
1278 if (pair->code != 9 /* && pair->code != 0 */)
1279 goto next_hdrvalue; // for mult. 10,20,30 values
1280 }
1281
1282 SINCE (R_2000)
1283 {
1284 BITCODE_BSd celweight = dxf_revcvt_lweight (_obj->CELWEIGHT);
1285 // clang-format off
1286 _obj->FLAGS = (celweight & 0x1f) |
1287 (_obj->ENDCAPS ? 0x60 : 0) |
1288 (_obj->JOINSTYLE ? 0x180 : 0) |
1289 (_obj->LWDISPLAY ? 0 : 0x200) |
1290 (_obj->XEDIT ? 0 : 0x400) |
1291 (_obj->EXTNAMES ? 0x800 : 0) |
1292 (_obj->PSTYLEMODE ? 0x2000 : 0) |
1293 (_obj->OLESTARTUP ? 0x4000 : 0);
1294 // clang-format on
1295 LOG_TRACE ("HEADER.%s => 0x%x\n", "FLAGS", (unsigned)_obj->FLAGS);
1296 dwg->Template.MEASUREMENT = _obj->MEASUREMENT;
1297 LOG_TRACE ("TEMPLATE.MEASUREMENT = HEADER.MEASUREMENT %d\n",
1298 (int)_obj->MEASUREMENT);
1299 }
1300
1301 dxf_free_pair (pair);
1302 return 0;
1303 }
1304
1305 static void
dxf_fixup_header(Dwg_Data * dwg)1306 dxf_fixup_header (Dwg_Data *dwg)
1307 {
1308 Dwg_Header_Variables *vars = &dwg->header_vars;
1309 Dwg_Header *hdr = &dwg->header;
1310 // Dwg_AuxHeader *aux = &dwg->auxheader;
1311 LOG_TRACE ("dxf_fixup_header\n");
1312
1313 if (vars->HANDSEED)
1314 vars->HANDSEED->handleref.code = 0;
1315 if (vars->DWGCODEPAGE)
1316 {
1317 if (strEQc (vars->DWGCODEPAGE, "ANSI_1252"))
1318 hdr->codepage = 30;
1319 else if (strEQc (vars->DWGCODEPAGE, "UTF-8"))
1320 hdr->codepage = 30;
1321 else if (strEQc (vars->DWGCODEPAGE, "US_ASCII"))
1322 hdr->codepage = 1;
1323 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-1"))
1324 hdr->codepage = 2;
1325 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-2"))
1326 hdr->codepage = 3;
1327 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-3")) // unused?
1328 hdr->codepage = 4;
1329 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-4"))
1330 hdr->codepage = 5;
1331 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-5"))
1332 hdr->codepage = 6;
1333 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-6"))
1334 hdr->codepage = 7;
1335 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-7"))
1336 hdr->codepage = 8;
1337 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-8"))
1338 hdr->codepage = 9;
1339 else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-9"))
1340 hdr->codepage = 10;
1341 else if (strEQc (vars->DWGCODEPAGE, "CP437"))
1342 hdr->codepage = 11;
1343 else if (strEQc (vars->DWGCODEPAGE, "CP850"))
1344 hdr->codepage = 12;
1345 else if (strEQc (vars->DWGCODEPAGE, "CP852"))
1346 hdr->codepage = 13;
1347 else if (strEQc (vars->DWGCODEPAGE, "CP855"))
1348 hdr->codepage = 14;
1349 else if (strEQc (vars->DWGCODEPAGE, "CP857"))
1350 hdr->codepage = 15;
1351 else if (strEQc (vars->DWGCODEPAGE, "CP860"))
1352 hdr->codepage = 16;
1353 else if (strEQc (vars->DWGCODEPAGE, "CP861"))
1354 hdr->codepage = 17;
1355 else if (strEQc (vars->DWGCODEPAGE, "CP863"))
1356 hdr->codepage = 18;
1357 else if (strEQc (vars->DWGCODEPAGE, "CP864"))
1358 hdr->codepage = 19;
1359 else if (strEQc (vars->DWGCODEPAGE, "CP865"))
1360 hdr->codepage = 20;
1361 else if (strEQc (vars->DWGCODEPAGE, "CP869"))
1362 hdr->codepage = 21;
1363 else if (strEQc (vars->DWGCODEPAGE, "CP932"))
1364 hdr->codepage = 22;
1365 else if (strEQc (vars->DWGCODEPAGE, "MACINTOSH"))
1366 hdr->codepage = 23;
1367 else if (strEQc (vars->DWGCODEPAGE, "BIG5"))
1368 hdr->codepage = 24;
1369 else if (strEQc (vars->DWGCODEPAGE, "CP949"))
1370 hdr->codepage = 25;
1371 else if (strEQc (vars->DWGCODEPAGE, "JOHAB"))
1372 hdr->codepage = 27;
1373 else if (strEQc (vars->DWGCODEPAGE, "CP866"))
1374 hdr->codepage = 27;
1375 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1250"))
1376 hdr->codepage = 28;
1377 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1251"))
1378 hdr->codepage = 29;
1379 else if (strEQc (vars->DWGCODEPAGE, "GB2312"))
1380 hdr->codepage = 31;
1381 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1253"))
1382 hdr->codepage = 32;
1383 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1254"))
1384 hdr->codepage = 33;
1385 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1255"))
1386 hdr->codepage = 34;
1387 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1256"))
1388 hdr->codepage = 35;
1389 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1257"))
1390 hdr->codepage = 36;
1391 else if (strEQc (vars->DWGCODEPAGE, "ANSI_874"))
1392 hdr->codepage = 37;
1393 else if (strEQc (vars->DWGCODEPAGE, "ANSI_932"))
1394 hdr->codepage = 38;
1395 else if (strEQc (vars->DWGCODEPAGE, "ANSI_936"))
1396 hdr->codepage = 39;
1397 else if (strEQc (vars->DWGCODEPAGE, "ANSI_949"))
1398 hdr->codepage = 40;
1399 else if (strEQc (vars->DWGCODEPAGE, "ANSI_950"))
1400 hdr->codepage = 41;
1401 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1258"))
1402 hdr->codepage = 44;
1403 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1361"))
1404 hdr->codepage = 42;
1405 else if (strEQc (vars->DWGCODEPAGE, "UTF-16"))
1406 hdr->codepage = 43;
1407 else if (strEQc (vars->DWGCODEPAGE, "ANSI_1258"))
1408 hdr->codepage = 44;
1409 else
1410 hdr->codepage = 0;
1411 }
1412 LOG_TRACE ("HEADER.codepage = %d [%s]\n", hdr->codepage, vars->DWGCODEPAGE);
1413
1414 // R_2007:
1415 // is_maint: 0x32 [RC 0]
1416 // zero_one_or_three: 0x3 [RC 0]
1417 // thumbnail_addr: 3360 [RL 0]
1418 // dwg_version: 0x1f [RC 0]
1419 // maint_version: 0x8 [RC 0]
1420 // codepage: 30 [RS 0]
1421 // R_2004+:
1422 // unknown_0: 0x0 [RC 0]
1423 // app_dwg_version: 0x1f [RC 0]
1424 // app_maint_version: 0x8 [RC 0]
1425 // security_type: 0 [RL 0]
1426 // rl_1c_address: 0 [RL 0]
1427 // summary_info_address: 3200 [RL 0]
1428 // vba_proj_address: 0 [RL 0]
1429 // r2004_header_address: 128 [RL 0]
1430
1431 // R_2000:
1432 // is_maint: 0xf [RC 0]
1433 // zero_one_or_three: 0x1 [RC 0]
1434 // thumbnail_addr: 220 [RL 0]
1435 // dwg_version: 0x1f [RC 0]
1436 // maint_version: 0x8 [RC 0]
1437 // codepage: 30 [RS 0]
1438
1439 if (hdr->version <= R_14)
1440 hdr->is_maint = 0x0;
1441 else if (hdr->version <= R_2000)
1442 {
1443 hdr->is_maint = 0xf; // 0x6 - 0xf
1444 hdr->zero_one_or_three = 1;
1445 hdr->thumbnail_address = 220;
1446 hdr->dwg_version = 0x21;
1447 hdr->maint_version = 0x8;
1448 }
1449 else if (hdr->version <= R_2004)
1450 hdr->is_maint = 0x68;
1451 else if (hdr->version <= R_2007)
1452 hdr->is_maint = 0x32;
1453 else if (hdr->version <= R_2010)
1454 hdr->is_maint = 0x6d;
1455 else if (hdr->version <= R_2013)
1456 hdr->is_maint = 0x7d;
1457 else if (hdr->version <= R_2018)
1458 hdr->is_maint = 0x4;
1459
1460 if (!vars->FINGERPRINTGUID)
1461 vars->FINGERPRINTGUID = strdup ("{00000000-0000-0000-0000-000000000000}");
1462 if (!vars->VERSIONGUID)
1463 vars->VERSIONGUID
1464 = strdup ("{DE6A95C3-2D01-4A77-AC28-3C42FCFFF657}"); // R_2000
1465 }
1466
1467 static int
dxf_classes_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1468 dxf_classes_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1469 {
1470 BITCODE_BL i;
1471 Dxf_Pair *pair = dxf_read_pair (dat);
1472 Dwg_Class *klass;
1473 const int is_binary = dat->opts & DWG_OPTS_DXFB;
1474 const char* t_type = dat->version >= R_2007 ? "TU" : "TV";
1475
1476 while (pair)
1477 { // read next class
1478 // add class (see decode)
1479 i = dwg->num_classes;
1480 if (i == 0)
1481 dwg->dwg_class = (Dwg_Class *)malloc (sizeof (Dwg_Class));
1482 else
1483 dwg->dwg_class = (Dwg_Class *)realloc (dwg->dwg_class,
1484 (i + 1) * sizeof (Dwg_Class));
1485 if (!dwg->dwg_class)
1486 {
1487 LOG_ERROR ("Out of memory");
1488 return DWG_ERR_OUTOFMEM;
1489 }
1490 restart:
1491 klass = &dwg->dwg_class[i];
1492 memset (klass, 0, sizeof (Dwg_Class));
1493 if (pair != NULL && pair->code == 0 && pair->value.s
1494 && strEQc (pair->value.s, "CLASS"))
1495 {
1496 dxf_free_pair (pair);
1497 pair = dxf_read_pair (dat);
1498 if (!pair)
1499 return 1;
1500 }
1501 else
1502 {
1503 LOG_ERROR ("2 CLASSES must be followed by 0 CLASS")
1504 DXF_RETURN_EOF (DWG_ERR_INVALIDDWG);
1505 return DWG_ERR_INVALIDDWG;
1506 }
1507 klass->number = 500 + i;
1508 while (pair != NULL && pair->code != 0)
1509 { // read until next 0 CLASS
1510 switch (pair->code)
1511 {
1512 case 1:
1513 if (pair->value.s)
1514 {
1515 const char *n = strEQc (pair->value.s, "ACDBDATATABLE")
1516 ? "DATATABLE"
1517 : pair->value.s;
1518 if (klass->dxfname)
1519 {
1520 LOG_ERROR ("Group 1 for CLASS %s already read",
1521 klass->dxfname);
1522 break;
1523 }
1524 STRADD_TV (klass->dxfname, n);
1525 if (dat->version >= R_2007)
1526 klass->dxfname_u = bit_utf8_to_TU ((char *)n, 0);
1527 LOG_TRACE ("CLASS[%d].dxfname = %s [TV 1]\n", i, n);
1528 }
1529 break;
1530 case 2:
1531 if (klass->cppname)
1532 {
1533 LOG_ERROR ("Group 2 for CLASS %s already read",
1534 klass->dxfname);
1535 break;
1536 }
1537 if (pair->value.s)
1538 {
1539 STRADD_T (klass->cppname, pair->value.s);
1540 }
1541 LOG_TRACE ("CLASS[%d].cppname = %s [%s 2]\n", i, pair->value.s,
1542 t_type);
1543 break;
1544 case 3:
1545 if (klass->appname)
1546 {
1547 LOG_ERROR ("Group 3 for CLASS %s already read",
1548 klass->dxfname);
1549 break;
1550 }
1551 if (pair->value.s)
1552 {
1553 STRADD_T (klass->appname, pair->value.s);
1554 }
1555 LOG_TRACE ("CLASS[%d].appname = %s [%s 3]\n", i, pair->value.s,
1556 t_type);
1557 break;
1558 case 90:
1559 klass->proxyflag = pair->value.l;
1560 LOG_TRACE ("CLASS[%d].proxyflag = %ld [BS 90]\n", i,
1561 pair->value.l);
1562 break;
1563 case 91:
1564 klass->num_instances = pair->value.l;
1565 LOG_TRACE ("CLASS[%d].num_instances = %ld [BL 91]\n", i,
1566 pair->value.l);
1567 break;
1568 case 280: // ie was_proxy
1569 klass->is_zombie = (BITCODE_B)pair->value.i;
1570 LOG_TRACE ("CLASS[%d].is_zombie = %d [B 280]\n", i,
1571 pair->value.i);
1572 if (is_binary)
1573 dat->byte++; // B => RS
1574 break;
1575 case 281: // ie is_entity
1576 // 1f2 for entities, 1f3 for objects
1577 klass->item_class_id = pair->value.i ? 0x1f2 : 0x1f3;
1578 LOG_TRACE ("CLASS[%d].item_class_id = 0x%x [BSx 281] (%s)\n", i,
1579 klass->item_class_id,
1580 pair->value.i ? "is_entity" : "is_object");
1581 if (is_binary)
1582 dat->byte++; // B => RS
1583 break;
1584 default:
1585 LOG_WARN ("Unknown DXF code for class[%d].%d", i, pair->code);
1586 break;
1587 }
1588 dxf_free_pair (pair);
1589 pair = dxf_read_pair (dat);
1590 if (!pair)
1591 {
1592 pair = dxf_read_pair (dat);
1593 if (!pair)
1594 return 1;
1595 }
1596 }
1597 if (klass->dxfname && klass->cppname && klass->appname
1598 && klass->item_class_id)
1599 {
1600 dwg->num_classes++;
1601 DXF_RETURN_ENDSEC (0)
1602 }
1603 else
1604 {
1605 DXF_RETURN_ENDSEC (0);
1606 goto restart; // without alloc
1607 }
1608 }
1609 dxf_free_pair (pair);
1610 return 0;
1611 }
1612
1613 static void
add_eed(Dwg_Object * restrict obj,const char * restrict name,Dxf_Pair * restrict pair)1614 add_eed (Dwg_Object *restrict obj, const char *restrict name,
1615 Dxf_Pair *restrict pair)
1616 {
1617 int code, size = 0, j;
1618 int i, prev = 0;
1619 Dwg_Eed *eed;
1620 Dwg_Data *dwg = obj->parent;
1621
1622 i = obj->tio.object->num_eed; // same layout for Object and Entity
1623 eed = obj->tio.object->eed;
1624
1625 // new eed pair
1626 if (pair->code < 1020 || pair->code > 1035) // no followup y and z pairs
1627 {
1628 if (i || eed)
1629 {
1630 eed = (Dwg_Eed *)realloc (eed, (i + 1) * sizeof (Dwg_Eed));
1631 if (!eed)
1632 {
1633 LOG_ERROR ("Out of memory");
1634 dwg_free_eed (obj);
1635 return;
1636 }
1637 if (i)
1638 memset (&eed[i], 0, sizeof (Dwg_Eed));
1639 }
1640 else
1641 {
1642 eed = (Dwg_Eed *)xcalloc (1, sizeof (Dwg_Eed));
1643 if (!eed)
1644 {
1645 LOG_ERROR ("Out of memory");
1646 dwg_free_eed (obj);
1647 return;
1648 }
1649 }
1650 obj->tio.object->eed = eed;
1651 obj->tio.object->num_eed++;
1652 }
1653 else // add to old eed
1654 i--;
1655 // search for previous size index
1656 for (j = i; j >= 0; j--)
1657 if (eed[j].handle.code)
1658 prev = j;
1659 if (!(prev >= 0 && prev <= i))
1660 {
1661 LOG_ERROR ("Invalid EED, no prev %d size 1000 code", prev);
1662 dwg_free_eed (obj);
1663 return;
1664 }
1665 assert (prev >= 0 && prev <= i);
1666 code = pair->code - 1000; // 1000
1667 if (code < 0 || code >= 1000)
1668 {
1669 LOG_ERROR ("Invalid DXF code %d", pair->code);
1670 dwg_free_eed (obj);
1671 return;
1672 }
1673 assert (code >= 0 && code < 100);
1674 LOG_TRACE ("EED[%d] code: %d ", i, code);
1675 switch (code)
1676 {
1677 case 0:
1678 {
1679 int len = pair->value.s ? strlen (pair->value.s) : 0;
1680 if (dwg->header.version < R_2007)
1681 {
1682 /* code [RC] + len [RS] + cp [RS] + str[len] */
1683 size = 1 + 2 + 2 + len;
1684 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size + 1);
1685 if (!eed[i].data)
1686 {
1687 LOG_ERROR ("Out of memory");
1688 dwg_free_eed (obj);
1689 return;
1690 }
1691 eed[i].data->code = code; // 1000
1692 eed[i].data->u.eed_0.is_tu = 0;
1693 eed[i].data->u.eed_0.length = len;
1694 eed[i].data->u.eed_0.codepage = dwg->header.codepage;
1695 if (len && len < 256)
1696 {
1697 LOG_TRACE ("string: \"%s\" [TV %d]\n", pair->value.s,
1698 size - 1);
1699 memcpy (eed[i].data->u.eed_0.string, pair->value.s, len + 1);
1700 }
1701 }
1702 else
1703 {
1704 /* code [RC] + length [RS] + 2*len [TU] */
1705 if (len && len < 32767)
1706 {
1707 BITCODE_TU tu = bit_utf8_to_TU (pair->value.s, 0);
1708 len = bit_wcs2len (tu);
1709 size = 1 + 2 + 2 + (len * 2); // now with padding
1710 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size + 2);
1711 if (!eed[i].data)
1712 {
1713 LOG_ERROR ("Out of memory");
1714 dwg_free_eed (obj);
1715 return;
1716 }
1717 eed[i].data->code = code;
1718 eed[i].data->u.eed_0.is_tu = 1;
1719 eed[i].data->u.eed_0_r2007.length = len;
1720 LOG_TRACE ("wstring: \"%s\" [TU %d]\n", pair->value.s, len);
1721 if (len)
1722 memcpy (eed[i].data->u.eed_0_r2007.string, tu,
1723 2 * (len + 1));
1724 free (tu);
1725 }
1726 }
1727 eed[i].size += size;
1728 }
1729 break;
1730 // 1001 is the name of the APPID handle, not part of size nor data
1731 case 1:
1732 obj->tio.object->num_eed--;
1733 prev = i;
1734 if (!pair->value.s || !*pair->value.s)
1735 {
1736 LOG_ERROR ("Invalid empty DXF code 1001");
1737 dwg_free_eed (obj);
1738 return;
1739 }
1740 if (strEQc (pair->value.s, "ACAD"))
1741 {
1742 dwg_add_handle (&eed[i].handle, 5, 0x12, NULL);
1743 LOG_TRACE ("handle: 5.1.12 [H] for APPID.%s\n", pair->value.s);
1744 }
1745 else
1746 {
1747 // search name in APPID table (if already added)
1748 BITCODE_H hdl;
1749 hdl = dwg_find_tablehandle_silent (dwg, pair->value.s, "APPID");
1750 if (hdl)
1751 {
1752 memcpy (&eed[i].handle, &hdl->handleref, sizeof (Dwg_Handle));
1753 eed[i].handle.code = 5;
1754 LOG_TRACE ("handle: %lX [H] for APPID.%s\n", hdl->absolute_ref,
1755 pair->value.s);
1756 }
1757 // needs to be postponed, because we don't have the tables yet
1758 else
1759 {
1760 char idx[12];
1761 snprintf (idx, 12, "%d", obj->index);
1762 eed[i].handle.code = 5;
1763 eed_hdls = array_push (eed_hdls, idx, pair->value.s, i);
1764 LOG_TRACE ("handle: ? [H} for APPID.%s later\n", pair->value.s);
1765 }
1766 }
1767 break;
1768 case 2: // 1002 . "{" => 0, or 1002 . "}" => 1
1769 /* code [RC] + close [RC] */
1770 size = 1 + 1;
1771 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1772 if (!eed[i].data)
1773 {
1774 LOG_ERROR ("Out of memory");
1775 dwg_free_eed (obj);
1776 return;
1777 }
1778 eed[i].data->code = code;
1779 eed[i].data->u.eed_2.close = strEQc (pair->value.s, "{") ? 0 : 1;
1780 LOG_TRACE ("close: %d\n", eed[i].data->u.eed_2.close);
1781 eed[i].size += size;
1782 break;
1783 case 4:
1784 {
1785 // BINARY
1786 //const char *pos = pair->value.s;
1787 //const unsigned len = strlen (pair->value.s);
1788 const unsigned blen = strlen (pair->value.s) >> 1;
1789 unsigned read;
1790 /* code [RC] + len+0 + length [RC] */
1791 size = 1 + blen + 1 + 1;
1792 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1793 if (!eed[i].data)
1794 {
1795 LOG_ERROR ("Out of memory");
1796 dwg_free_eed (obj);
1797 return;
1798 }
1799 eed[i].data->code = code; // 1004
1800 eed[i].data->u.eed_4.length = blen;
1801 LOG_TRACE ("binary[%d]: ", blen);
1802 if ((read = in_hex2bin (eed[i].data->u.eed_4.data, pair->value.s, blen) != blen))
1803 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
1804 eed[i].size += size;
1805 }
1806 break;
1807 case 10: // DWG_VT_POINT3D
1808 case 11:
1809 case 12:
1810 case 13:
1811 case 14:
1812 case 15:
1813 /* code [RC] + 3*RD */
1814 size = 1 + (3 * 8);
1815 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1816 if (!eed[i].data)
1817 {
1818 LOG_ERROR ("Out of memory");
1819 dwg_free_eed (obj);
1820 return;
1821 }
1822 eed[i].data->code = code;
1823 eed[i].data->u.eed_10.point.x = pair->value.d;
1824 eed[i].size += size;
1825 break;
1826 case 20:
1827 case 21:
1828 case 22:
1829 case 23:
1830 case 24:
1831 case 25:
1832 if (i < 0)
1833 return;
1834 if (!eed[i].data || eed[i].data->code != code - 10)
1835 {
1836 LOG_ERROR ("Wrong EED DXF code %d, expected %d", code + 1000,
1837 eed[i].data ? eed[i].data->code + 1010 : 1020)
1838 return;
1839 }
1840 eed[i].data->u.eed_10.point.y = pair->value.d;
1841 break;
1842 case 30:
1843 case 31:
1844 case 32:
1845 case 33:
1846 case 34:
1847 case 35:
1848 if (i < 0)
1849 return;
1850 if (!eed[i].data || eed[i].data->code != code - 20)
1851 {
1852 LOG_ERROR ("Wrong EED DXF code %d, expected %d", code + 1000,
1853 eed[i].data ? eed[i].data->code + 1020 : 1030)
1854 return;
1855 }
1856 eed[i].data->u.eed_10.point.z = pair->value.d;
1857 LOG_TRACE ("3dpoint: (%f,%f,%f)\n", eed[i].data->u.eed_10.point.x,
1858 eed[i].data->u.eed_10.point.y, pair->value.d);
1859 break;
1860 case 40:
1861 case 41:
1862 case 42:
1863 /* code [RC] + 3*RD */
1864 size = 1 + 8;
1865 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1866 if (!eed[i].data)
1867 {
1868 LOG_ERROR ("Out of memory");
1869 dwg_free_eed (obj);
1870 return;
1871 }
1872 eed[i].data->code = code; // 1071
1873 eed[i].data->u.eed_40.real = pair->value.d;
1874 LOG_TRACE ("real: %f\n", pair->value.d);
1875 eed[i].size += size;
1876 break;
1877 case 70:
1878 /* code [RC] + RS */
1879 size = 1 + 2;
1880 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1881 if (!eed[i].data)
1882 {
1883 LOG_ERROR ("Out of memory");
1884 dwg_free_eed (obj);
1885 return;
1886 }
1887 eed[i].data->code = code; // 1071
1888 eed[i].data->u.eed_70.rs = pair->value.i;
1889 LOG_TRACE ("short: %d\n", pair->value.i);
1890 eed[i].size += size;
1891 break;
1892 case 71:
1893 /* code [RC] + RL */
1894 size = 1 + 4;
1895 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1896 if (!eed[i].data)
1897 {
1898 LOG_ERROR ("Out of memory");
1899 dwg_free_eed (obj);
1900 return;
1901 }
1902 eed[i].data->code = code; // 1071
1903 eed[i].data->u.eed_71.rl = pair->value.l;
1904 LOG_TRACE ("long: %ld\n", pair->value.l);
1905 eed[i].size += size;
1906 break;
1907 case 5:
1908 {
1909 // HANDLE (absref)
1910 const char *pos = pair->value.s;
1911 unsigned long l = 0;
1912 /* code [RC] + RLL */
1913 size = 1 + 8;
1914 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1915 if (!eed[i].data)
1916 {
1917 LOG_ERROR ("Out of memory");
1918 dwg_free_eed (obj);
1919 return;
1920 }
1921 eed[i].data->code = code; // 1005
1922 sscanf (pos, "%lX", &l);
1923 eed[i].data->u.eed_5.entity = (BITCODE_RLL)l;
1924 LOG_TRACE ("entity: %lX [RLL]\n", l);
1925 eed[i].size += size;
1926 break;
1927 }
1928 default:
1929 LOG_ERROR ("Not yet implemented EED[%d] code %d", i, pair->code);
1930 }
1931 // new size block or not?
1932 if (!eed[i].handle.code)
1933 {
1934 // add to prev. size
1935 if (i != prev)
1936 {
1937 eed[prev].size += eed[i].size;
1938 eed[i].size = 0;
1939 }
1940 LOG_TRACE ("EED[%d] size: %d\n", prev, eed[prev].size);
1941 }
1942 else if (eed[i].size)
1943 LOG_TRACE ("EED[%d] size: %d\n", i, eed[i].size);
1944 return;
1945 }
1946
1947 int
is_table_name(const char * restrict name)1948 is_table_name (const char *restrict name)
1949 {
1950 return strEQc (name, "LTYPE") || strEQc (name, "VPORT")
1951 || strEQc (name, "VPORT") || strEQc (name, "APPID")
1952 || strEQc (name, "BLOCK") || strEQc (name, "LAYER")
1953 || strEQc (name, "DIMSTYLE") || strEQc (name, "STYLE")
1954 || strEQc (name, "VIEW") || strEQc (name, "VX")
1955 || strEQc (name, "UCS") || strEQc (name, "BLOCK_RECORD")
1956 || strEQc (name, "BLOCK_HEADER");
1957 }
1958
1959 #define CHK_array(i, array) \
1960 if (i < 0 || i >= (int)o->num_##array || !o->array) \
1961 return NULL; \
1962 assert (o->array); \
1963 assert (i >= 0 && i < (int)o->num_##array)
1964
1965 static Dxf_Pair *
add_LTYPE_dashes(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)1966 add_LTYPE_dashes (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
1967 Dxf_Pair *restrict pair)
1968 {
1969 Dwg_Object_LTYPE *o = obj->tio.object->tio.LTYPE;
1970 Dwg_Data *dwg = obj->parent;
1971 int num_dashes = (int)o->num_dashes;
1972 int is_tu = 0;
1973
1974 o->dashes
1975 = (Dwg_LTYPE_dash *)xcalloc (o->num_dashes, sizeof (Dwg_LTYPE_dash));
1976 if (!o->dashes)
1977 {
1978 o->num_dashes = 0;
1979 return NULL;
1980 }
1981 for (int j = -1; j < num_dashes;)
1982 {
1983 if (!pair || pair->code == 0)
1984 return pair;
1985 else if (pair->code == 49)
1986 {
1987 j++;
1988 CHK_array (j, dashes);
1989 o->dashes[j].length = pair->value.d;
1990 LOG_TRACE ("LTYPE.dashes[%d].length = %f [BD 49]\n", j,
1991 pair->value.d);
1992 PRE (R_13)
1993 o->pattern_len += pair->value.d;
1994 }
1995 else if (pair->code == 74)
1996 {
1997 CHK_array (j, dashes);
1998 o->dashes[j].shape_flag = pair->value.i;
1999 LOG_TRACE ("LTYPE.dashes[%d].shape_flag = %d [BS 74]\n", j,
2000 pair->value.i);
2001 if (o->dashes[j].shape_flag & 2)
2002 o->has_strings_area = 1;
2003 }
2004 else if (pair->code == 75)
2005 {
2006 if (j < 0)
2007 j++;
2008 CHK_array (j, dashes);
2009 o->dashes[j].complex_shapecode = pair->value.i;
2010 LOG_TRACE ("LTYPE.dashes[%d].complex_shapecode = %d [BS 75]\n", j,
2011 pair->value.i);
2012 }
2013 else if (pair->code == 340)
2014 {
2015 if (j < 0)
2016 j++;
2017 CHK_array (j, dashes);
2018 o->dashes[j].style
2019 = dwg_add_handleref (obj->parent, 5, pair->value.u, obj);
2020 LOG_TRACE ("LTYPE.dashes[%d].style = " FORMAT_REF " [H 340]\n", j,
2021 ARGS_REF (o->dashes[j].style));
2022 }
2023 else if (pair->code == 44)
2024 {
2025 CHK_array (j, dashes);
2026 o->dashes[j].x_offset = pair->value.d;
2027 LOG_TRACE ("LTYPE.dashes[%d].x_offset = %f [BD 44]\n", j,
2028 pair->value.d);
2029 }
2030 else if (pair->code == 45)
2031 {
2032 CHK_array (j, dashes);
2033 o->dashes[j].y_offset = pair->value.d;
2034 LOG_TRACE ("LTYPE.dashes[%d].y_offset = %f [BD 45]\n", j,
2035 pair->value.d);
2036 }
2037 else if (pair->code == 46)
2038 {
2039 CHK_array (j, dashes);
2040 o->dashes[j].scale = pair->value.d;
2041 LOG_TRACE ("LTYPE.dashes[%d].scale = %f [BD 46]\n", j,
2042 pair->value.d);
2043 }
2044 else if (pair->code == 50)
2045 {
2046 CHK_array (j, dashes);
2047 o->dashes[j].rotation = deg2rad (pair->value.d);
2048 LOG_TRACE ("LTYPE.dashes[%d].rotation = %f [BD 50]\n", j,
2049 o->dashes[j].rotation);
2050 }
2051 else if (pair->code == 9)
2052 {
2053 static int dash_i = 0;
2054 is_tu = obj->parent->header.version >= R_2007;
2055 CHK_array (j, dashes);
2056 o->dashes[j].text = dwg_add_u8_input (obj->parent, pair->value.s);
2057 LOG_TRACE ("LTYPE.dashes[%d].text = %s [T 9]\n", j, pair->value.s);
2058 // write into strings_area
2059 if (!o->strings_area)
2060 o->strings_area = (BITCODE_TF)xcalloc (is_tu ? 512 : 256, 1);
2061 if (is_tu)
2062 {
2063 bit_wcs2cpy ((BITCODE_TU)&o->strings_area[dash_i],
2064 (BITCODE_TU)o->dashes[j].text);
2065 dash_i += (strlen (pair->value.s) * 2) + 2;
2066 }
2067 else
2068 {
2069 strcpy ((char *)&o->strings_area[dash_i], o->dashes[j].text);
2070 dash_i += strlen (pair->value.s) + 1;
2071 }
2072 }
2073 else
2074 break; // not a Dwg_LTYPE_dash
2075
2076 dxf_free_pair (pair);
2077 pair = dxf_read_pair (dat);
2078 }
2079 return pair;
2080 }
2081
2082 static Dxf_Pair *
add_MLINESTYLE_lines(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2083 add_MLINESTYLE_lines (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2084 Dxf_Pair *restrict pair)
2085 {
2086 int num_lines = pair->value.i;
2087 Dwg_Object_MLINESTYLE *o = obj->tio.object->tio.MLINESTYLE;
2088 Dwg_Data *dwg = obj->parent;
2089 o->num_lines = num_lines;
2090 LOG_TRACE ("MLINESTYLE.num_lines = %d [RC 71]\n", num_lines);
2091 o->lines = (Dwg_MLINESTYLE_line *)xcalloc (num_lines,
2092 sizeof (Dwg_MLINESTYLE_line));
2093 if (!o->lines)
2094 {
2095 o->num_lines = 0;
2096 return NULL;
2097 }
2098
2099 for (int j = -1; j < (int)num_lines;)
2100 {
2101 dxf_free_pair (pair);
2102 pair = dxf_read_pair (dat);
2103 if (pair == NULL || pair->code == 0)
2104 return pair;
2105 else if (pair->code == 49)
2106 {
2107 j++;
2108 CHK_array (j, lines);
2109 o->lines[j].offset = pair->value.d;
2110 LOG_TRACE ("MLINESTYLE.lines[%d].offset = %f [BD 49]\n", j,
2111 pair->value.d);
2112 }
2113 else if (pair->code == 62)
2114 {
2115 if (j < 0)
2116 j++;
2117 CHK_array (j, lines);
2118 o->lines[j].color.index = pair->value.i;
2119 LOG_TRACE ("MLINESTYLE.lines[%d].color.index = %d [CMC 62]\n", j,
2120 pair->value.i);
2121 }
2122 else if (pair->code == 420)
2123 {
2124 if (j < 0)
2125 j++;
2126 CHK_array (j, lines);
2127 o->lines[j].color.rgb = pair->value.u;
2128 LOG_TRACE ("MLINESTYLE.lines[%d].color.rgb = %08X [CMC 420]\n", j,
2129 pair->value.u);
2130 }
2131 else if (pair->code == 6)
2132 {
2133 if (j < 0)
2134 j++;
2135 CHK_array (j, lines);
2136 o->lines[j].lt_index = 0;
2137 o->lines[j].lt_ltype = NULL;
2138 if (strEQc (pair->value.s, "BYLAYER")
2139 || strEQc (pair->value.s, "ByLayer"))
2140 {
2141 // TODO SHRT_MAX, but should be -1 really
2142 o->lines[j].lt_index = 32767;
2143 LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = -1 [BSd 6]\n", j);
2144 if (dwg->header.from_version >= R_2018)
2145 goto mline_hdl;
2146 }
2147 else if (strEQc (pair->value.s, "BYBLOCK")
2148 || strEQc (pair->value.s, "ByBlock"))
2149 {
2150 o->lines[j].lt_index = 32766;
2151 LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = -2 [BSd 6]\n", j);
2152 if (dwg->header.from_version >= R_2018)
2153 goto mline_hdl;
2154 }
2155 else if (strEQc (pair->value.s, "CONTINUOUS")
2156 || strEQc (pair->value.s, "Continuous"))
2157 {
2158 o->lines[j].lt_index = 0;
2159 LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = 0 [BSd 6]\n", j);
2160 if (dwg->header.from_version >= R_2018)
2161 goto mline_hdl;
2162 }
2163 else // lookup on LTYPE_CONTROL list
2164 mline_hdl:
2165 {
2166 BITCODE_H hdl;
2167 o->lines[j].lt_index
2168 = (BITCODE_BSd)strtol (pair->value.s, NULL, 10);
2169 if (o->lines[j].lt_index)
2170 LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = %d [BSd 6]\n", j,
2171 (int)o->lines[j].lt_index);
2172 if ((hdl = dwg_find_tablehandle_silent (dwg, pair->value.s,
2173 "LTYPE")))
2174 {
2175 hdl->handleref.code = 5;
2176 o->lines[j].lt_ltype = hdl;
2177 LOG_TRACE ("MLINESTYLE.lines[%d].lt_ltype %s => " FORMAT_REF
2178 " [H 6]\n",
2179 j, pair->value.s, ARGS_REF (hdl));
2180 }
2181 }
2182 }
2183 else
2184 break; // not a Dwg_MLINESTYLE_line
2185 }
2186 return pair;
2187 }
2188
2189 static Dxf_Pair *
new_LWPOLYLINE(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2190 new_LWPOLYLINE (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2191 Dxf_Pair *restrict pair)
2192 {
2193 BITCODE_BL num_points = pair->value.u;
2194 Dwg_Entity_LWPOLYLINE *o = obj->tio.entity->tio.LWPOLYLINE;
2195 int j = -1;
2196
2197 o->num_points = num_points;
2198 LOG_TRACE ("LWPOLYLINE.num_points = %u [BS 90]\n", num_points);
2199 o->points = (BITCODE_2RD *)xcalloc (num_points, sizeof (BITCODE_2RD));
2200 if (!o->points)
2201 {
2202 o->num_points = 0;
2203 return NULL;
2204 }
2205
2206 while (pair != NULL && pair->code != 0)
2207 {
2208 dxf_free_pair (pair);
2209 pair = dxf_read_pair (dat);
2210 if (pair == NULL || pair->code == 0)
2211 {
2212 LOG_TRACE ("LWPOLYLINE.flag = %d [BS 70]\n", o->flag);
2213 return pair;
2214 }
2215 else if (pair->code == 43)
2216 {
2217 o->const_width = pair->value.d;
2218 if (pair->value.d != 0.0)
2219 o->flag |= 4;
2220 LOG_TRACE ("LWPOLYLINE.const_width = %f [BD 43]\n", pair->value.d);
2221 }
2222 else if (pair->code == 70)
2223 {
2224 if (pair->value.i & 1) /* only if closed or not */
2225 o->flag |= 512;
2226 else if (pair->value.i & 128) /* plinegen? */
2227 o->flag |= 128;
2228 LOG_TRACE ("LWPOLYLINE.flag = %d [BS 70]\n", o->flag);
2229 }
2230 else if (pair->code == 38)
2231 {
2232 o->elevation = pair->value.d;
2233 if (pair->value.d != 0.0)
2234 o->flag |= 8;
2235 LOG_TRACE ("LWPOLYLINE.elevation = %f [38 BD]\n", pair->value.d);
2236 }
2237 else if (pair->code == 39)
2238 {
2239 o->thickness = pair->value.d;
2240 if (pair->value.d != 0.0)
2241 o->flag |= 2;
2242 LOG_TRACE ("LWPOLYLINE.thickness = %f [BD 39]\n", pair->value.d);
2243 }
2244 else if (pair->code == 210)
2245 {
2246 o->extrusion.x = pair->value.d;
2247 }
2248 else if (pair->code == 220)
2249 {
2250 o->extrusion.y = pair->value.d;
2251 }
2252 else if (pair->code == 230)
2253 {
2254 o->extrusion.z = pair->value.d;
2255 if (o->extrusion.x == 0.0 && o->extrusion.y == 0.0)
2256 o->extrusion.z = (o->extrusion.z <= 0.0) ? -1.0 : 1.0;
2257 if (o->extrusion.x != 0.0 || o->extrusion.y != 0.0
2258 || o->extrusion.z != 1.0)
2259 o->flag |= 1;
2260 LOG_TRACE ("LWPOLYLINE.extrusion = (%f, %f, %f) [BE 210]\n",
2261 o->extrusion.x, o->extrusion.y, o->extrusion.z);
2262 }
2263 else if (pair->code == 10)
2264 {
2265 j++; // we always start with 10 (I hope)
2266
2267 #define CHK_points \
2268 if (j < 0 || j >= (int)o->num_points || !o->points) \
2269 return NULL; \
2270 assert (o->points); \
2271 assert (o->num_points > 0); \
2272 assert (j >= 0 && j < (int)o->num_points)
2273
2274 CHK_points;
2275 o->points[j].x = pair->value.d;
2276 }
2277 else if (pair->code == 20)
2278 {
2279 CHK_points;
2280 LOG_TRACE ("LWPOLYLINE.points[%d] = (%f, %f) [2RD 10]\n", j,
2281 o->points[j].x, pair->value.d);
2282 o->points[j].y = pair->value.d;
2283 }
2284 else if (pair->code == 42)
2285 {
2286 if (!o->num_bulges)
2287 {
2288 o->bulges
2289 = (BITCODE_BD *)xcalloc (num_points, sizeof (BITCODE_BD));
2290 if (!o->bulges)
2291 {
2292 o->num_bulges = 0;
2293 return NULL;
2294 }
2295 o->num_bulges = num_points;
2296 o->flag |= 16;
2297 }
2298 CHK_array (j, bulges);
2299 o->bulges[j] = pair->value.d;
2300 LOG_TRACE ("LWPOLYLINE.bulges[%d] = %f [BD 42]\n", j, pair->value.d);
2301 }
2302 else if (pair->code == 91)
2303 {
2304 if (!j)
2305 {
2306 o->vertexids
2307 = (BITCODE_BL *)xcalloc (num_points, sizeof (BITCODE_BL));
2308 if (!o->vertexids)
2309 {
2310 o->num_vertexids = 0;
2311 return NULL;
2312 }
2313 o->num_vertexids = num_points;
2314 }
2315 CHK_array (j, vertexids);
2316 o->vertexids[j] = pair->value.i;
2317 LOG_TRACE ("LWPOLYLINE.vertexids[%d] = %d [BL 91]\n", j,
2318 pair->value.i);
2319 }
2320 else if (pair->code == 40) // not const_width
2321 {
2322 if (!j)
2323 {
2324 o->widths = (Dwg_LWPOLYLINE_width *)xcalloc (
2325 num_points, sizeof (Dwg_LWPOLYLINE_width));
2326 if (!o->widths)
2327 {
2328 o->num_widths = 0;
2329 return NULL;
2330 }
2331 o->flag |= 4;
2332 o->num_widths = num_points;
2333 }
2334 CHK_array (j, widths);
2335 o->widths[j].start = pair->value.d;
2336 LOG_TRACE ("LWPOLYLINE.widths[%d].start = %f [BD 40]\n", j,
2337 pair->value.d);
2338 }
2339 else if (pair->code == 41 && (o->flag & 4)) // not const_width
2340 {
2341 CHK_array (j, widths);
2342 o->widths[j].end = pair->value.d;
2343 LOG_TRACE ("LWPOLYLINE.widths[%d].end = %f [BD 41]\n", j,
2344 pair->value.d);
2345 }
2346 else if (pair->code >= 1000 && pair->code < 1999)
2347 {
2348 add_eed (obj, "LWPOLYLINE", pair);
2349 }
2350 else
2351 {
2352 LOG_ERROR ("Invalid DXF code %d for %s", pair->code, "LWPOLYLINE");
2353 return NULL;
2354 }
2355 }
2356 return pair;
2357 }
2358 #undef CHK_points
2359
2360 // only code 1
2361 static Dxf_Pair *
add_3DSOLID_encr(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2362 add_3DSOLID_encr (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2363 Dxf_Pair *restrict pair)
2364 {
2365 Dwg_Entity_3DSOLID *o = obj->tio.entity->tio._3DSOLID;
2366 int i = 0, total = 0;
2367 o->num_blocks = 1;
2368 o->encr_sat_data = (char **)xcalloc (2, sizeof (char *));
2369 if (!o->encr_sat_data)
2370 {
2371 o->num_blocks = 0;
2372 return NULL;
2373 }
2374 o->encr_sat_data[0] = NULL;
2375 o->block_size = (BITCODE_BL *)xcalloc (2, sizeof (BITCODE_BL));
2376 if (!o->block_size)
2377 {
2378 o->num_blocks = 0;
2379 return NULL;
2380 }
2381
2382 while (pair != NULL && (pair->code == 1 || pair->code == 3))
2383 {
2384 int len;
2385 if (!pair->value.s)
2386 {
2387 dxf_free_pair (pair);
2388 pair = dxf_read_pair (dat);
2389 continue;
2390 }
2391 len = strlen (pair->value.s) + 1; // + the \n
2392 if (len > 100000) // chunked into blocks of size 4096
2393 {
2394 LOG_ERROR ("Out of memory");
2395 return NULL;
2396 }
2397 if (!total || !o->encr_sat_data[0])
2398 {
2399 total = len;
2400 o->encr_sat_data[0] = (char *)malloc (total + 1); // + the \0
2401 if (!o->encr_sat_data[0])
2402 {
2403 LOG_ERROR ("Out of memory");
2404 return NULL;
2405 }
2406 // memcpy (o->encr_sat_data[0], pair->value.s, len + 1);
2407 strcpy ((char *)o->encr_sat_data[0], pair->value.s);
2408 }
2409 else
2410 {
2411 total += len;
2412 o->encr_sat_data[0]
2413 = (char *)realloc (o->encr_sat_data[0], total + 1);
2414 if (!o->encr_sat_data[0])
2415 {
2416 LOG_ERROR ("Out of memory");
2417 return NULL;
2418 }
2419 strcat ((char *)o->encr_sat_data[0], pair->value.s);
2420 }
2421 if (pair->code == 1)
2422 {
2423 strcat ((char *)o->encr_sat_data[0], "\n");
2424 // For the replacement of "^ " with "^" see below
2425 i++;
2426 }
2427
2428 dxf_free_pair (pair);
2429 pair = dxf_read_pair (dat);
2430 }
2431 LOG_TRACE ("%s.block_size[0]: %d\n", obj->name, total);
2432
2433 if (o->version == 1)
2434 {
2435 int idx = 0;
2436 o->unknown = 1; // ??
2437 o->acis_data = (BITCODE_RC *)xcalloc (1, total + 1);
2438 if (!o->acis_data)
2439 return NULL;
2440 for (i = 0; i < total; i++)
2441 {
2442 if (o->encr_sat_data[0][i] == '^' && i <= total
2443 && o->encr_sat_data[0][i + 1] == ' ')
2444 {
2445 o->acis_data[idx++] = 'A';
2446 i++;
2447 }
2448 else if (o->encr_sat_data[0][i] <= 32)
2449 o->acis_data[idx++] = o->encr_sat_data[0][i];
2450 else
2451 o->acis_data[idx++] = 159 - o->encr_sat_data[0][i];
2452 }
2453 o->acis_data[idx] = '\0';
2454 o->block_size[0] = idx;
2455 LOG_TRACE ("%s.acis_data:\n%s\n", obj->name, o->acis_data);
2456 }
2457
2458 return pair;
2459 }
2460
2461 static Dxf_Pair *
add_MESH(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2462 add_MESH (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2463 Dxf_Pair *restrict pair)
2464 {
2465 Dwg_Entity_MESH *o = obj->tio.entity->tio.MESH;
2466 int j = 0;
2467 int vector = 0;
2468
2469 // valid entry code: 91
2470 if (pair->code == 91)
2471 {
2472 vector = pair->code;
2473 o->num_subdiv_vertex = pair->value.u;
2474 LOG_TRACE ("MESH.num_subdiv_vertex = %u [BL 91]\n", pair->value.u);
2475 if (pair->value.u)
2476 {
2477 o->subdiv_vertex = (BITCODE_3BD *)xcalloc (o->num_subdiv_vertex,
2478 sizeof (BITCODE_3BD));
2479 if (!o->subdiv_vertex)
2480 {
2481 o->num_subdiv_vertex = 0;
2482 return NULL;
2483 }
2484 }
2485 }
2486
2487 while (pair->code != 0)
2488 {
2489 dxf_free_pair (pair);
2490 pair = dxf_read_pair (dat);
2491
2492 if (pair == NULL || pair->code == 0)
2493 return pair;
2494 else if (pair->code == 92)
2495 {
2496 j = 0;
2497 vector = pair->code;
2498 o->num_vertex = pair->value.u;
2499 LOG_TRACE ("MESH.num_vertex = %u [BL 92]\n", pair->value.u);
2500 if (pair->value.u)
2501 {
2502 o->vertex = (BITCODE_3BD *)xcalloc (o->num_vertex,
2503 sizeof (BITCODE_3BD));
2504 if (!o->vertex)
2505 {
2506 o->num_vertex = 0;
2507 return NULL;
2508 }
2509 }
2510 }
2511 else if (pair->code == 93)
2512 {
2513 j = 0;
2514 vector = pair->code;
2515 o->num_faces = pair->value.u;
2516 LOG_TRACE ("MESH.num_faces = %u [BL %d]\n", pair->value.u,
2517 pair->code);
2518 if (pair->value.u)
2519 {
2520 o->faces
2521 = (BITCODE_BL *)xcalloc (o->num_faces, sizeof (BITCODE_BL));
2522 if (!o->faces)
2523 {
2524 o->num_faces = 0;
2525 return NULL;
2526 }
2527 }
2528 }
2529 else if (pair->code == 94)
2530 {
2531 j = 0;
2532 vector = pair->code;
2533 o->num_edges = pair->value.u;
2534 LOG_TRACE ("MESH.num_edges = %u [BL %d]\n", pair->value.u,
2535 pair->code);
2536 if (pair->value.u) // from face - to face
2537 {
2538 o->edges = (Dwg_MESH_edge *)xcalloc (o->num_edges,
2539 sizeof (Dwg_MESH_edge));
2540 if (!o->edges)
2541 {
2542 o->num_edges = 0;
2543 return NULL;
2544 }
2545 }
2546 }
2547 else if (pair->code == 95)
2548 {
2549 j = 0;
2550 vector = pair->code;
2551 o->num_crease = pair->value.u;
2552 LOG_TRACE ("MESH.num_crease = %u [BL %d]\n", pair->value.u,
2553 pair->code);
2554 if (pair->value.u)
2555 {
2556 o->crease
2557 = (BITCODE_BD *)xcalloc (o->num_crease, sizeof (BITCODE_BD));
2558 if (!o->crease)
2559 {
2560 o->num_crease = 0;
2561 return NULL;
2562 }
2563 }
2564 }
2565 else if (pair->code == 10)
2566 {
2567 if (vector == 91)
2568 {
2569 CHK_array (j, subdiv_vertex);
2570 o->subdiv_vertex[j].x = pair->value.d;
2571 }
2572 else if (vector == 92)
2573 {
2574 CHK_array (j, vertex);
2575 o->vertex[j].x = pair->value.d;
2576 }
2577 else
2578 goto mesh_error;
2579 }
2580 else if (pair->code == 20)
2581 {
2582 if (vector == 91)
2583 {
2584 CHK_array (j, subdiv_vertex);
2585 o->subdiv_vertex[j].y = pair->value.d;
2586 }
2587 else if (vector == 92)
2588 {
2589 CHK_array (j, vertex);
2590 o->vertex[j].y = pair->value.d;
2591 }
2592 else
2593 goto mesh_error;
2594 }
2595 else if (pair->code == 30)
2596 {
2597 if (vector == 91)
2598 {
2599 CHK_array (j, subdiv_vertex);
2600 o->subdiv_vertex[j].z = pair->value.d;
2601 LOG_TRACE ("MESH.subdiv_vertex[%d] = (%f, %f, %f) [3BD 10]\n", j,
2602 o->subdiv_vertex[j].x, o->subdiv_vertex[j].y,
2603 o->subdiv_vertex[j].z);
2604 j++;
2605 }
2606 else if (vector == 92)
2607 {
2608 CHK_array (j, vertex);
2609 o->vertex[j].z = pair->value.d;
2610 LOG_TRACE ("MESH.vertex[%d] = (%f, %f, %f) [3BD 10]\n", j,
2611 o->vertex[j].x, o->vertex[j].y, o->vertex[j].z);
2612 j++;
2613 }
2614 else
2615 goto mesh_error;
2616 }
2617 else if (pair->code == 90)
2618 {
2619 if (vector == 93)
2620 {
2621 CHK_array (j, faces);
2622 o->faces[j] = pair->value.u;
2623 LOG_TRACE ("MESH.faces[%d] = %u [BL %d]\n", j, pair->value.u,
2624 pair->code);
2625 j++;
2626 }
2627 else if (vector == 94)
2628 {
2629 int i = j / 2;
2630 CHK_array (i, edges);
2631 assert (j < (int)(2 * o->num_edges));
2632 if (j % 2 == 0)
2633 {
2634 o->edges[i].idxfrom = pair->value.u;
2635 }
2636 else
2637 {
2638 o->edges[i].idxto = pair->value.u;
2639 LOG_TRACE ("MESH.edges[%d] = (%u, %u) [2BL %d]\n", i,
2640 o->edges[i].idxfrom, pair->value.u, pair->code);
2641 }
2642 j++;
2643 }
2644 else if (vector == 95)
2645 {
2646 o->num_crease = pair->value.u;
2647 LOG_TRACE ("MESH.num_crease = %u [BL %d]\n", pair->value.u,
2648 pair->code);
2649 if (pair->value.u) // from face - to face
2650 {
2651 o->crease
2652 = (double *)xcalloc (o->num_crease, sizeof (double));
2653 if (!o->crease)
2654 {
2655 o->num_crease = 0;
2656 return NULL;
2657 }
2658 }
2659 }
2660 else
2661 goto mesh_error;
2662 }
2663 else if (pair->code == 140)
2664 {
2665 if (vector == 95)
2666 {
2667 CHK_array (j, crease);
2668 o->crease[j] = pair->value.u;
2669 LOG_TRACE ("MESH.crease[%d] = %u [BD %d]\n", j, pair->value.u,
2670 pair->code);
2671 j++;
2672 }
2673 else
2674 goto mesh_error;
2675 }
2676 else if (pair->code >= 1000 && pair->code < 1999)
2677 {
2678 add_eed (obj, "MESH", pair);
2679 }
2680 else
2681 {
2682 mesh_error:
2683 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "MESH");
2684 }
2685 }
2686 return pair;
2687 }
2688
2689 static Dxf_Pair *
add_HATCH(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2690 add_HATCH (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2691 Dxf_Pair *restrict pair)
2692 {
2693 BITCODE_BL num_paths; // 91
2694 Dwg_Entity_HATCH *o = obj->tio.entity->tio.HATCH;
2695 int is_plpath = 0;
2696 int j = -1;
2697 int k = -1;
2698 int l = -1;
2699 int hdl_idx = -1;
2700 bool next_330_boundary_handles = false;
2701
2702 // valid entry codes
2703 if (pair->code == 91)
2704 {
2705 o->num_paths = pair->value.u;
2706 LOG_TRACE ("HATCH.num_paths = %u [BS 91]\n", o->num_paths);
2707 o->paths
2708 = (Dwg_HATCH_Path *)xcalloc (o->num_paths, sizeof (Dwg_HATCH_Path));
2709 if (!o->paths)
2710 {
2711 o->num_paths = 0;
2712 return NULL;
2713 }
2714 }
2715 else if (pair->code == 78)
2716 {
2717 o->num_deflines = pair->value.l;
2718 LOG_TRACE ("HATCH.num_deflines = %ld [BS 78]\n", pair->value.l);
2719 o->deflines = (Dwg_HATCH_DefLine *)xcalloc (pair->value.l,
2720 sizeof (Dwg_HATCH_DefLine));
2721 if (!o->deflines)
2722 {
2723 o->num_deflines = 0;
2724 return NULL;
2725 }
2726 }
2727 if (pair->code == 453)
2728 {
2729 o->num_colors = pair->value.l;
2730 LOG_TRACE ("HATCH.num_colors = %ld [BL 453]\n", pair->value.l);
2731 o->colors = (Dwg_HATCH_Color *)xcalloc (pair->value.l,
2732 sizeof (Dwg_HATCH_Color));
2733 if (!o->colors)
2734 {
2735 o->num_colors = 0;
2736 return NULL;
2737 }
2738 }
2739
2740 while (pair->code != 0)
2741 {
2742 dxf_free_pair (pair);
2743 pair = dxf_read_pair (dat);
2744
2745 if (pair == NULL || pair->code == 0 || pair->code == 75)
2746 return pair;
2747 else if (pair->code == 92)
2748 {
2749 j++;
2750
2751 #define CHK_paths \
2752 if (!o->paths || j < 0 || j >= (int)o->num_paths) \
2753 { \
2754 LOG_ERROR ("HATCH no paths or wrong j %u\n", j); \
2755 return NULL; \
2756 } \
2757 assert (o->paths); \
2758 assert (j >= 0); \
2759 assert (j < (int)o->num_paths)
2760
2761 CHK_paths;
2762 o->paths[j].flag = pair->value.u;
2763 LOG_TRACE ("HATCH.paths[%d].flag = %u [BL 92]\n", j, pair->value.u);
2764 is_plpath = pair->value.u & 2;
2765 o->has_derived = pair->value.u & 4;
2766 LOG_TRACE ("HATCH.has_derived = %d [B 0]\n", o->has_derived);
2767 }
2768 else if (pair->code == 93)
2769 {
2770 CHK_paths;
2771 o->paths[j].num_segs_or_paths = pair->value.u;
2772 LOG_TRACE ("HATCH.paths[%d].num_segs_or_paths = %u [BL 93]\n", j,
2773 pair->value.u);
2774 k = -1;
2775 if (pair->value.u && !is_plpath)
2776 { /* segs */
2777 o->paths[j].segs = (Dwg_HATCH_PathSeg *)xcalloc (
2778 pair->value.u, sizeof (Dwg_HATCH_PathSeg));
2779 if (!o->paths[j].segs)
2780 {
2781 o->paths[j].num_segs_or_paths = 0;
2782 return NULL;
2783 }
2784 }
2785 else if (pair->value.u)
2786 { /* polyline path */
2787 o->paths[j].polyline_paths = (Dwg_HATCH_PolylinePath *)xcalloc (
2788 pair->value.u, sizeof (Dwg_HATCH_PolylinePath));
2789 if (!o->paths[j].polyline_paths)
2790 {
2791 o->paths[j].num_segs_or_paths = 0;
2792 return NULL;
2793 }
2794 }
2795 }
2796 else if (pair->code == 72)
2797 {
2798 CHK_paths;
2799 if (!is_plpath)
2800 {
2801 k++;
2802 assert (k >= 0);
2803 if (j < (int)o->num_paths
2804 && k < (int)o->paths[j].num_segs_or_paths)
2805 {
2806 o->paths[j].segs[k].curve_type = pair->value.i;
2807 LOG_TRACE (
2808 "HATCH.paths[%d].segs[%d].curve_type = %d [RC 72]\n", j,
2809 k, pair->value.i);
2810 }
2811 }
2812 else
2813 {
2814 o->paths[j].bulges_present = pair->value.i;
2815 LOG_TRACE ("HATCH.paths[%d].bulges_present = %d [RC 72]\n", j,
2816 pair->value.i);
2817 }
2818 }
2819 else if (pair->code == 73 && is_plpath && pair->value.i)
2820 {
2821 CHK_paths;
2822 o->paths[j].closed = pair->value.i;
2823 LOG_TRACE ("HATCH.paths[%d].closed = %d [RC 73]\n", j,
2824 pair->value.i);
2825 }
2826 else if (pair->code == 94 && !is_plpath && pair->value.l)
2827 {
2828 CHK_paths;
2829
2830 #define CHK_segs \
2831 if (!o->paths[j].segs || k < 0 || k >= (int)o->paths[j].num_segs_or_paths) \
2832 { \
2833 LOG_ERROR ("HATCH no paths[%d].segs or wrong k %d\n", j, k); \
2834 return NULL; \
2835 } \
2836 assert (o->paths[j].segs); \
2837 assert (k >= 0); \
2838 assert (k < (int)o->paths[j].num_segs_or_paths)
2839
2840 CHK_segs;
2841 o->paths[j].segs[k].degree = pair->value.l;
2842 LOG_TRACE ("HATCH.paths[%d].segs[%d].degree = %ld [BL 94]\n", j, k,
2843 pair->value.l);
2844 }
2845 else if (pair->code == 74 && !is_plpath)
2846 {
2847 CHK_paths;
2848 CHK_segs;
2849 o->paths[j].segs[k].is_periodic = pair->value.i;
2850 LOG_TRACE ("HATCH.paths[%d].segs[%d].is_periodic = %d [B 74]\n", j,
2851 k, pair->value.i);
2852 }
2853 else if (pair->code == 95 && !is_plpath)
2854 {
2855 CHK_paths;
2856 CHK_segs;
2857 o->paths[j].segs[k].num_knots = pair->value.l;
2858 LOG_TRACE ("HATCH.paths[%d].segs[%d].num_knots = %ld [BL 95]\n", j,
2859 k, pair->value.l);
2860 o->paths[j].segs[k].knots
2861 = (double *)xcalloc (pair->value.l, sizeof (double));
2862 if (!o->paths[j].segs[k].knots)
2863 {
2864 o->paths[j].segs[k].num_knots = 0;
2865 return NULL;
2866 }
2867 l = -1;
2868 }
2869 else if (pair->code == 96 && !is_plpath)
2870 {
2871 CHK_paths;
2872 CHK_segs;
2873 o->paths[j].segs[k].num_control_points = pair->value.l;
2874 LOG_TRACE (
2875 "HATCH.paths[%d].segs[%d].num_control_points = %ld [BL 96]\n", j,
2876 k, pair->value.l);
2877 o->paths[j].segs[k].control_points
2878 = (Dwg_HATCH_ControlPoint *)xcalloc (
2879 pair->value.l, sizeof (Dwg_HATCH_ControlPoint));
2880 if (!o->paths[j].segs[k].control_points)
2881 {
2882 o->paths[j].segs[k].num_control_points = 0;
2883 return NULL;
2884 }
2885 l = -1;
2886 }
2887 else if (pair->code == 10 && !is_plpath && !o->num_seeds)
2888 {
2889 CHK_paths;
2890 CHK_segs;
2891 switch (o->paths[j].segs[k].curve_type)
2892 {
2893 case 1: /* LINE */
2894 o->paths[j].segs[k].first_endpoint.x = pair->value.d;
2895 // LOG_TRACE ("HATCH.paths[%d].segs[%d].first_endpoint.x = %f [10
2896 // 2BD]\n",
2897 // j, k, pair->value.d);
2898 break;
2899 case 2: /* CIRCULAR ARC */
2900 case 3: /* ELLIPTICAL ARC */
2901 o->paths[j].segs[k].center.x = pair->value.d;
2902 // LOG_TRACE ("HATCH.paths[%d].segs[%d].center.x = %f [10
2903 // 2BD]\n",
2904 // j, k, pair->value.d);
2905 break;
2906 case 4: /* SPLINE */
2907 l++;
2908
2909 #define CHK_control_points \
2910 if (!o->paths[j].segs || l < 0 \
2911 || l >= (int)o->paths[j].segs[k].num_control_points) \
2912 { \
2913 LOG_ERROR ("HATCH no paths[%d].segs or " \
2914 "wrong l %d control_points index\n", j, l); \
2915 return NULL; \
2916 } \
2917 assert (l >= 0); \
2918 assert (l < (int)o->paths[j].segs[k].num_control_points)
2919
2920 CHK_control_points;
2921 o->paths[j].segs[k].control_points[l].point.x = pair->value.d;
2922 // LOG_TRACE
2923 // ("HATCH.paths[%d].segs[%d].control_points[%d].point.x = %f [10
2924 // 2BD]\n",
2925 // j, k, l, pair->value.d);
2926 break;
2927 default:
2928 LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
2929 "for DXF %d",
2930 j, k, o->paths[j].segs[k].curve_type, pair->code);
2931 }
2932 }
2933 else if (pair->code == 11 && !is_plpath && !o->num_seeds)
2934 {
2935 CHK_paths;
2936 CHK_segs;
2937 switch (o->paths[j].segs[k].curve_type)
2938 {
2939 case 1: /* LINE */
2940 o->paths[j].segs[k].second_endpoint.x = pair->value.d;
2941 // LOG_TRACE ("HATCH.paths[%d].segs[%d].second_endpoint.x = %f
2942 // [2BD 11]\n",
2943 // j, k, pair->value.d);
2944 break;
2945 case 3: /* ELLIPTICAL ARC */
2946 o->paths[j].segs[k].endpoint.x = pair->value.d;
2947 // LOG_TRACE ("HATCH.paths[%d].segs[%d].endpoint.x = %f [
2948 // 2BD 11]\n",
2949 // j, k, pair->value.d);
2950 break;
2951 case 4: /* SPLINE */
2952 l++;
2953 CHK_paths;
2954 CHK_segs;
2955 CHK_control_points;
2956 o->paths[j].segs[k].fitpts[l].x = pair->value.d;
2957 // LOG_TRACE ("HATCH.paths[%d].segs[%d].fitpts[%d].x = %f [
2958 // 2RD 11]\n",
2959 // j, k, l, pair->value.d);
2960 break;
2961 default:
2962 LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
2963 "for DXF %d",
2964 j, k, o->paths[j].segs[k].curve_type, pair->code);
2965 }
2966 }
2967 else if (pair->code == 20 && !is_plpath && !o->num_seeds)
2968 {
2969 CHK_paths;
2970 CHK_segs;
2971 switch (o->paths[j].segs[k].curve_type)
2972 {
2973 case 1: /* LINE */
2974 o->paths[j].segs[k].first_endpoint.y = pair->value.d;
2975 LOG_TRACE ("HATCH.paths[%d].segs[%d].first_endpoint = (%f, %f) "
2976 "[2RD 10]\n",
2977 j, k, o->paths[j].segs[k].first_endpoint.x,
2978 pair->value.d);
2979 break;
2980 case 2: /* CIRCULAR ARC */
2981 case 3: /* ELLIPTICAL ARC */
2982 o->paths[j].segs[k].center.y = pair->value.d;
2983 LOG_TRACE (
2984 "HATCH.paths[%d].segs[%d].center = (%f, %f) [2RD 10]\n", j,
2985 k, o->paths[j].segs[k].center.x, pair->value.d);
2986 break;
2987 case 4: /* SPLINE */
2988 CHK_control_points;
2989 o->paths[j].segs[k].control_points[l].point.y = pair->value.d;
2990 LOG_TRACE ("HATCH.paths[%d].segs[%d].control_points[%d].point = "
2991 "(%f, %f) [2RD 10]\n",
2992 j, k, l,
2993 o->paths[j].segs[k].control_points[l].point.x,
2994 pair->value.d);
2995 break;
2996 default:
2997 LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
2998 "for DXF %d",
2999 j, k, o->paths[j].segs[k].curve_type, pair->code);
3000 }
3001 }
3002 else if (pair->code == 21 && !is_plpath && !o->num_seeds
3003 && pair->value.d != 0.0)
3004 {
3005 CHK_paths;
3006 CHK_segs;
3007 switch (o->paths[j].segs[k].curve_type)
3008 {
3009 case 1: /* LINE */
3010 o->paths[j].segs[k].second_endpoint.y = pair->value.d;
3011 LOG_TRACE ("HATCH.paths[%d].segs[%d].second_endpoint = (%f, %f) "
3012 "[2RD 11]\n",
3013 j, k, o->paths[j].segs[k].second_endpoint.x,
3014 pair->value.d);
3015 break;
3016 case 3: /* ELLIPTICAL ARC */
3017 o->paths[j].segs[k].endpoint.y = pair->value.d;
3018 LOG_TRACE (
3019 "HATCH.paths[%d].segs[%d].endpoint = (%f, %f) [2RD 11]\n", j,
3020 k, o->paths[j].segs[k].endpoint.x, pair->value.d);
3021 break;
3022 case 4: /* SPLINE */
3023 CHK_control_points;
3024 o->paths[j].segs[k].fitpts[l].y = pair->value.d;
3025 LOG_TRACE ("HATCH.paths[%d].segs[%d].fitpts[%d].y = (%f, %f) "
3026 "[2RD 11]\n",
3027 j, k, l, o->paths[j].segs[k].fitpts[l].x,
3028 pair->value.d);
3029 break;
3030 default:
3031 LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3032 "for DXF %d",
3033 j, k, o->paths[j].segs[k].curve_type, pair->code);
3034 }
3035 }
3036 else if (pair->code == 40 && !is_plpath)
3037 {
3038 CHK_paths;
3039 CHK_segs;
3040 switch (o->paths[j].segs[k].curve_type)
3041 {
3042 case 2: /* CIRCULAR ARC */
3043 o->paths[j].segs[k].radius = pair->value.d;
3044 LOG_TRACE ("HATCH.paths[%d].segs[%d].radius = %f [BD 40]\n", j,
3045 k, pair->value.d);
3046 break;
3047 case 3: /* ELLIPTICAL ARC */
3048 o->paths[j].segs[k].minor_major_ratio = pair->value.d;
3049 LOG_TRACE (
3050 "HATCH.paths[%d].segs[%d].minor_major_ratio = %f [BD 40]\n",
3051 j, k, pair->value.d);
3052 break;
3053 case 4: /* SPLINE */
3054 if (l >= 0 && o->paths[j].segs[k].is_rational)
3055 {
3056 CHK_control_points;
3057 o->paths[j].segs[k].control_points[l].weight = pair->value.d;
3058 LOG_TRACE ("HATCH.paths[%d].segs[%d].control_points[%d]."
3059 "weight = %f [BD 40]\n",
3060 j, k, l, pair->value.d);
3061 }
3062 else
3063 {
3064 #define CHK_knots \
3065 if (!o->paths[j].segs || \
3066 !o->paths[j].segs[k].knots || \
3067 l < 0 || \
3068 l >= (int)o->paths[j].segs[k].num_knots) \
3069 { \
3070 LOG_ERROR ("HATCH no paths[%d].segs[%d].knots or " \
3071 "wrong l %d knots index\n", j, k, l); \
3072 return NULL; \
3073 } \
3074 assert (l >= 0); \
3075 assert (l < (int)o->paths[j].segs[k].num_knots)
3076
3077 l++;
3078 CHK_knots;
3079 o->paths[j].segs[k].knots[l] = pair->value.d;
3080 LOG_TRACE (
3081 "HATCH.paths[%d].segs[%d].knots[%d] = %f [BD 40]\n", j,
3082 k, l, pair->value.d);
3083 if (l == (int)o->paths[j].segs[k].num_knots - 1) // last 40
3084 l = -1;
3085 }
3086 break;
3087 default:
3088 LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3089 "for DXF %d",
3090 j, k, o->paths[j].segs[k].curve_type, pair->code);
3091 }
3092 }
3093 else if (pair->code == 50 && !is_plpath)
3094 {
3095 CHK_paths;
3096 CHK_segs;
3097 switch (o->paths[j].segs[k].curve_type)
3098 {
3099 case 2: /* CIRCULAR ARC */
3100 case 3: /* ELLIPTICAL ARC */
3101 o->paths[j].segs[k].start_angle = deg2rad (pair->value.d);
3102 LOG_TRACE ("HATCH.paths[%d].segs[%d].start_angle = %f [BD 50]\n",
3103 j, k, pair->value.d);
3104 break;
3105 default:
3106 LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3107 "for DXF %d",
3108 j, k, o->paths[j].segs[k].curve_type, pair->code);
3109 }
3110 }
3111 else if (pair->code == 51 && !is_plpath)
3112 {
3113 CHK_paths;
3114 CHK_segs;
3115 switch (o->paths[j].segs[k].curve_type)
3116 {
3117 case 2: /* CIRCULAR ARC */
3118 case 3: /* ELLIPTICAL ARC */
3119 o->paths[j].segs[k].end_angle = deg2rad (pair->value.d);
3120 LOG_TRACE ("HATCH.paths[%d].segs[%d].end_angle = %f [BD 51]\n",
3121 j, k, pair->value.d);
3122 break;
3123 default:
3124 LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3125 "for DXF %d",
3126 j, k, o->paths[j].segs[k].curve_type, pair->code);
3127 }
3128 }
3129 else if (pair->code == 73 && !is_plpath)
3130 {
3131 CHK_paths;
3132 CHK_segs;
3133 switch (o->paths[j].segs[k].curve_type)
3134 {
3135 case 2: /* CIRCULAR ARC */
3136 case 3: /* ELLIPTICAL ARC */
3137 o->paths[j].segs[k].is_ccw = pair->value.i;
3138 LOG_TRACE ("HATCH.paths[%d].segs[%d].is_ccw = %d [B 73]\n", j, k,
3139 pair->value.i);
3140 break;
3141 default: // SPLINE 4
3142 o->paths[j].segs[k].is_rational = pair->value.i;
3143 LOG_TRACE ("HATCH.paths[%d].segs[%d].is_rational = %d [B 73]\n",
3144 j, k, pair->value.i);
3145 }
3146 }
3147 else if (pair->code == 10 && is_plpath && !o->num_seeds)
3148 {
3149 k++;
3150 CHK_paths;
3151
3152 #define CHK_polyline_paths \
3153 if (!o->paths[j].polyline_paths || k < 0 \
3154 || k >= (int)o->paths[j].num_segs_or_paths) \
3155 { \
3156 LOG_ERROR ("HATCH no paths[%d].polyline_paths or wrong k %d\n", j, k); \
3157 return NULL; \
3158 } \
3159 assert (o->paths[j].polyline_paths); \
3160 assert (k >= 0); \
3161 assert (k < (int)o->paths[j].num_segs_or_paths)
3162
3163 CHK_polyline_paths;
3164 o->paths[j].polyline_paths[k].point.x = pair->value.d;
3165 // LOG_TRACE ("HATCH.paths[%d].polyline_paths[%d].point.x = %f [BD 10
3166 // ]\n",
3167 // j, k, pair->value.d);
3168 }
3169 else if (pair->code == 20 && is_plpath && !o->num_seeds)
3170 {
3171 CHK_paths;
3172 CHK_polyline_paths;
3173 o->paths[j].polyline_paths[k].point.y = pair->value.d;
3174 LOG_TRACE (
3175 "HATCH.paths[%d].polyline_paths[%d].point = (%f, %f) [2RD 10]\n",
3176 j, k, o->paths[j].polyline_paths[k].point.x, pair->value.d);
3177 }
3178 else if (pair->code == 42 && is_plpath)
3179 {
3180 CHK_paths;
3181 CHK_polyline_paths;
3182 o->paths[j].polyline_paths[k].bulge = pair->value.d;
3183 LOG_TRACE ("HATCH.paths[%d].polyline_paths[%d].bulge = %f [BD 42]\n",
3184 j, k, pair->value.d);
3185 }
3186 else if (pair->code == 97 && !is_plpath)
3187 {
3188 CHK_paths;
3189 CHK_segs;
3190 if (k < 0 || o->paths[j].segs[k].curve_type != 4)
3191 {
3192 next_330_boundary_handles = true;
3193 o->paths[j].num_boundary_handles = pair->value.l;
3194 //o->num_boundary_handles += pair->value.l;
3195 LOG_TRACE ("HATCH.paths[%d].num_boundary_handles = %ld [BL 97]\n",
3196 j, pair->value.l);
3197 k = 0;
3198 }
3199 else
3200 {
3201 next_330_boundary_handles = false;
3202 o->paths[j].segs[k].num_fitpts = pair->value.l;
3203 LOG_TRACE (
3204 "HATCH.paths[%d].segs[%d].num_fitpts = %ld [BL 97]\n", j, k,
3205 pair->value.l);
3206 }
3207 }
3208 else if (pair->code == 97 && is_plpath)
3209 {
3210 CHK_paths;
3211 o->paths[j].num_boundary_handles = pair->value.l;
3212 next_330_boundary_handles = true;
3213 //o->num_boundary_handles += pair->value.l;
3214 LOG_TRACE ("HATCH.paths[%d].num_boundary_handles = %ld [BL 97] (1)\n", j,
3215 pair->value.l);
3216 k = 0;
3217 }
3218 else if (pair->code == 78)
3219 {
3220 o->num_deflines = pair->value.l;
3221 LOG_TRACE ("HATCH.num_deflines = %ld [BS 78]\n", pair->value.l);
3222 o->deflines = (Dwg_HATCH_DefLine *)xcalloc (
3223 pair->value.l, sizeof (Dwg_HATCH_DefLine));
3224 if (!o->deflines)
3225 {
3226 o->num_deflines = 0;
3227 return NULL;
3228 }
3229 j = -1;
3230 }
3231 else if (pair->code == 53 && o->num_deflines)
3232 {
3233 j++;
3234
3235 #define CHK_deflines \
3236 if (!o->deflines || j < 0 || j >= (int)o->num_deflines) \
3237 { \
3238 LOG_ERROR ("HATCH no deflines or wrong j %d", j); \
3239 return NULL; \
3240 } \
3241 assert (j >= 0); \
3242 assert (j < (int)o->num_deflines)
3243
3244 CHK_deflines;
3245 o->deflines[j].angle = deg2rad (pair->value.d);
3246 LOG_TRACE ("HATCH.deflines[%d].angle = %f [BD 53]\n", j,
3247 o->deflines[j].angle);
3248 }
3249 else if (pair->code == 43 && o->num_deflines)
3250 {
3251 CHK_deflines;
3252 o->deflines[j].pt0.x = pair->value.d;
3253 LOG_TRACE ("HATCH.deflines[%d].pt0.x = %f [BD 43]\n", j,
3254 pair->value.d);
3255 }
3256 else if (pair->code == 44 && o->num_deflines)
3257 {
3258 CHK_deflines;
3259 o->deflines[j].pt0.y = pair->value.d;
3260 LOG_TRACE ("HATCH.deflines[%d].pt0.y = %f [BD 44]\n", j,
3261 pair->value.d);
3262 }
3263 else if (pair->code == 45 && o->num_deflines)
3264 {
3265 CHK_deflines;
3266 o->deflines[j].offset.x = pair->value.d;
3267 LOG_TRACE ("HATCH.deflines[%d].offset.x = %f [BD 45]\n", j,
3268 pair->value.d);
3269 }
3270 else if (pair->code == 46 && o->num_deflines)
3271 {
3272 CHK_deflines;
3273 o->deflines[j].offset.y = pair->value.d;
3274 LOG_TRACE ("HATCH.deflines[%d].offset.y = %f [BD 46]\n", j,
3275 pair->value.d);
3276 }
3277 else if (pair->code == 79 && o->num_deflines)
3278 {
3279 CHK_deflines;
3280 o->deflines[j].num_dashes = pair->value.u;
3281 LOG_TRACE ("HATCH.deflines[%d].num_dashes = %u [BS 79]\n", j,
3282 pair->value.u);
3283 if (pair->value.u)
3284 {
3285 o->deflines[j].dashes
3286 = (BITCODE_BD *)xcalloc (pair->value.u, sizeof (BITCODE_BD));
3287 if (!o->deflines[j].dashes)
3288 {
3289 o->deflines[j].num_dashes = 0;
3290 return NULL;
3291 }
3292 }
3293 k = -1;
3294 }
3295 else if (pair->code == 49 && o->num_deflines && j >= 0)
3296 {
3297 CHK_deflines;
3298 if (!o->deflines[j].dashes)
3299 {
3300 LOG_ERROR ("DXF 79 num_dashes missing for HATCH.dashes 49")
3301 goto unknown_HATCH;
3302 }
3303 k++;
3304 if (!o->deflines[j].dashes || k < 0
3305 || k >= (int)o->deflines[j].num_dashes)
3306 return NULL;
3307 assert (k >= 0);
3308 assert (k < (int)o->deflines[j].num_dashes);
3309 o->deflines[j].dashes[k] = pair->value.d;
3310 LOG_TRACE ("HATCH.deflines[%d].dashes[%d] = %f [BD 49]\n", j, k,
3311 pair->value.d);
3312 }
3313 else if (pair->code == 47)
3314 {
3315 o->pixel_size = pair->value.d;
3316 LOG_TRACE ("HATCH.pixel_size = %f [BD 47]\n", pair->value.d);
3317 }
3318 else if (pair->code == 98)
3319 {
3320 o->num_seeds = pair->value.u;
3321 LOG_TRACE ("HATCH.num_seeds = %u [BL 98]\n", pair->value.u);
3322 if (pair->value.u)
3323 {
3324 o->seeds = (BITCODE_2RD *)xcalloc (pair->value.u,
3325 sizeof (BITCODE_2RD));
3326 if (!o->seeds)
3327 {
3328 o->num_seeds = 0;
3329 return NULL;
3330 }
3331 }
3332 k = -1;
3333 }
3334 else if (pair->code == 10 && o->num_seeds)
3335 {
3336 k++;
3337
3338 #define CHK_seeds \
3339 if (!o->seeds || k < 0 || k >= (int)o->num_seeds) \
3340 { \
3341 LOG_ERROR ("HATCH no seeds or wrong k %d", k); \
3342 return NULL; \
3343 } \
3344 assert (k >= 0); \
3345 assert (k < (int)o->num_seeds)
3346
3347 CHK_seeds;
3348 o->seeds[k].x = pair->value.d;
3349 // LOG_TRACE ("HATCH.seeds[%d].x = %f [10 2RD]\n",
3350 // k, pair->value.d);
3351 }
3352 else if (pair->code == 20 && o->num_seeds)
3353 {
3354 CHK_seeds;
3355 o->seeds[k].y = pair->value.d;
3356 LOG_TRACE ("HATCH.seeds[%d] = (%f, %f) [2RD 10]\n", k, o->seeds[k].x,
3357 pair->value.d);
3358 }
3359 else if (pair->code == 330
3360 && next_330_boundary_handles
3361 && j >= 0 && j < (int)o->num_paths
3362 && o->paths[j].num_boundary_handles
3363 && (hdl_idx + 1) < (int)o->paths[j].num_boundary_handles)
3364 {
3365 BITCODE_H ref
3366 = dwg_add_handleref (obj->parent, 4, pair->value.u, obj);
3367 CHK_paths;
3368 hdl_idx++;
3369 if ((unsigned)hdl_idx > o->paths[j].num_boundary_handles)
3370 o->paths[j].num_boundary_handles = (unsigned)hdl_idx;
3371 if (!o->paths[j].boundary_handles)
3372 o->paths[j].boundary_handles = (BITCODE_H *)xcalloc (o->paths[j].num_boundary_handles, sizeof (BITCODE_H));
3373 else
3374 o->paths[j].boundary_handles = (BITCODE_H *)realloc (o->paths[j].boundary_handles,
3375 o->paths[j].num_boundary_handles * sizeof (BITCODE_H));
3376 LOG_TRACE ("HATCH.paths[%d].num_boundary_handles = %u\n", j,
3377 (unsigned)o->paths[j].num_boundary_handles);
3378 if (!o->paths[j].boundary_handles)
3379 {
3380 o->paths[j].num_boundary_handles = 0;
3381 LOG_ERROR ("! HATCH.paths[%d].boundary_handles", j);
3382 return NULL;
3383 }
3384 o->paths[j].boundary_handles[hdl_idx] = ref;
3385 LOG_TRACE ("HATCH.paths[%d].boundary_handles[%d] = " FORMAT_REF " [H 330]\n",
3386 j, hdl_idx, ARGS_REF (ref));
3387 }
3388 else if (pair->code == 453)
3389 {
3390 o->num_colors = pair->value.u;
3391 LOG_TRACE ("HATCH.num_colors = %u [BL 453]\n", pair->value.u);
3392 if (pair->value.u)
3393 {
3394 o->colors = (Dwg_HATCH_Color *)xcalloc (
3395 pair->value.u, sizeof (Dwg_HATCH_Color));
3396 if (!o->colors)
3397 {
3398 o->num_colors = 0;
3399 return NULL;
3400 }
3401 }
3402 j = -1;
3403 }
3404 else if (pair->code == 463 && o->num_colors)
3405 {
3406 j++;
3407 if (!o->colors || j < 0 || j >= (int)o->num_colors)
3408 return NULL;
3409 assert (j >= 0);
3410 assert (j < (int)o->num_colors);
3411 o->colors[j].shift_value = pair->value.d;
3412 LOG_TRACE ("HATCH.colors[%d].shift_value = %f [BD 463]\n", j,
3413 pair->value.d);
3414 }
3415 else if (pair->code == 63 && o->num_colors)
3416 {
3417 if (!o->colors || j < 0 || j >= (int)o->num_colors)
3418 return NULL;
3419 assert (j < (int)o->num_colors);
3420 o->colors[j].color.index = pair->value.i;
3421 LOG_TRACE ("HATCH.colors[%d].color.index = %u [CMC 63]\n", j,
3422 pair->value.i);
3423 }
3424 else if (pair->code == 421 && o->num_colors)
3425 {
3426 if (!o->colors || j < 0 || j >= (int)o->num_colors)
3427 return NULL;
3428 assert (j >= 0);
3429 assert (j < (int)o->num_colors);
3430 o->colors[j].color.rgb = pair->value.u;
3431 LOG_TRACE ("HATCH.colors[%d].color.rgb = %08X [CMC 421]\n", j,
3432 pair->value.u);
3433 }
3434 else if (pair->code == 431 && o->num_colors)
3435 {
3436 if (!o->colors || j < 0 || j >= (int)o->num_colors)
3437 return NULL;
3438 assert (j >= 0);
3439 assert (j < (int)o->num_colors);
3440 if (dat->version >= R_2007)
3441 o->colors[j].color.name
3442 = (BITCODE_T)bit_utf8_to_TU (pair->value.s, 0);
3443 else
3444 o->colors[j].color.name = strdup (pair->value.s);
3445 LOG_TRACE ("HATCH.colors[%d].color.name = %s [CMC 431]\n", j,
3446 pair->value.s);
3447 }
3448 else if (pair->code == 470)
3449 {
3450 dwg_dynapi_entity_set_value (o, "HATCH", "gradient_name",
3451 &pair->value, 1);
3452 LOG_TRACE ("HATCH.gradient_name = %s [T 470]\n", pair->value.s);
3453 }
3454 else if (pair->code == 450)
3455 {
3456 o->is_gradient_fill = pair->value.u;
3457 LOG_TRACE ("HATCH.is_gradient_fill = %u [BL 450]\n", pair->value.u);
3458 }
3459 else if (pair->code == 451)
3460 {
3461 o->reserved = pair->value.u;
3462 LOG_TRACE ("HATCH.reserved = %u [BL 451]\n", pair->value.u);
3463 }
3464 else if (pair->code == 460)
3465 {
3466 o->gradient_angle = deg2rad (pair->value.d);
3467 LOG_TRACE ("HATCH.gradient_angle = %f [BD 460]\n", pair->value.d);
3468 }
3469 else if (pair->code == 461)
3470 {
3471 o->gradient_shift = pair->value.d;
3472 LOG_TRACE ("HATCH.gradient_shift = %f [BD 461]\n", pair->value.d);
3473 }
3474 else if (pair->code == 452)
3475 {
3476 o->single_color_gradient = pair->value.u;
3477 LOG_TRACE ("HATCH.single_color_gradient = %u [BL 452]\n",
3478 pair->value.u);
3479 }
3480 else if (pair->code == 462)
3481 {
3482 o->gradient_tint = pair->value.d;
3483 LOG_TRACE ("HATCH.gradient_tint = %f [BD 462]\n", pair->value.d);
3484 }
3485 else if (pair->code >= 1000 && pair->code < 1999)
3486 {
3487 add_eed (obj, "HATCH", pair);
3488 }
3489 else
3490 {
3491 unknown_HATCH:
3492 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "HATCH");
3493 }
3494 }
3495 return pair;
3496 }
3497 #undef CHK_paths
3498 #undef CHK_polyline_paths
3499 #undef CHK_deflines
3500 #undef CHK_seeds
3501
3502 static Dxf_Pair *
add_MULTILEADER_lines(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair,Dwg_LEADER_Node * lnode)3503 add_MULTILEADER_lines (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
3504 Dxf_Pair *restrict pair, Dwg_LEADER_Node *lnode)
3505 {
3506 Dwg_Entity_MULTILEADER *o = obj->tio.entity->tio.MULTILEADER;
3507 if (!lnode)
3508 return NULL;
3509 lnode->num_lines = 0;
3510 if (pair->code == 304 && strEQc (pair->value.s, "LEADER_LINE{"))
3511 {
3512 int i = -1, j = -1, k = -1;
3513 Dwg_MLEADER_AnnotContext *ctx = &o->ctx;
3514 lnode->lines = (Dwg_LEADER_Line *)xcalloc (1, sizeof (Dwg_LEADER_Line));
3515 if (!lnode->lines)
3516 {
3517 lnode->num_lines = 0;
3518 return NULL;
3519 }
3520
3521 // lines and breaks
3522 while (pair->code != 305 && pair->code != 0)
3523 {
3524 Dwg_LEADER_Line *lline = &lnode->lines[0];
3525 dxf_free_pair (pair);
3526 pair = dxf_read_pair (dat);
3527 if (!pair)
3528 return NULL;
3529 switch (pair->code)
3530 {
3531 case 10:
3532 i++;
3533 lnode->num_lines = i + 1;
3534 LOG_TRACE ("%s.leaders[].num_lines = %d\n", obj->name, i + 1);
3535 if (i > 0)
3536 {
3537 lnode->lines = (Dwg_LEADER_Line *)realloc (
3538 lnode->lines,
3539 lnode->num_lines * sizeof (Dwg_LEADER_Line));
3540 if (!lnode->lines)
3541 {
3542 lnode->num_lines = 0;
3543 LOG_ERROR ("Out of memory");
3544 return NULL;
3545 }
3546 }
3547 lline = &lnode->lines[i];
3548 memset (lline, 0, sizeof (Dwg_LEADER_Line));
3549 lline->num_breaks = 0;
3550 j++;
3551 lline->num_points = j + 1;
3552 lline->points = (BITCODE_3BD *)realloc (
3553 lline->points, lline->num_points * sizeof (BITCODE_3BD));
3554 memset (&lline->points[j], 0, sizeof (BITCODE_3BD));
3555 lline->points[j].x = pair->value.d;
3556 LOG_TRACE ("%s.leaders[].lines[%d].points[%d].x = %f [BD %d]\n",
3557 obj->name, i, j, pair->value.d, pair->code);
3558 break;
3559 case 20:
3560 #define CHK_points \
3561 if (j < 0 || j >= (int)lline->num_points) \
3562 { \
3563 LOG_ERROR ("MULTILEADER wrong j %d points index", j); \
3564 return NULL; \
3565 } \
3566 assert (j >= 0 && j < (int)lline->num_points)
3567
3568 #define CHK_breaks \
3569 if (k < 0 || k >= (int)lline->num_breaks) \
3570 { \
3571 LOG_ERROR ("MULTILEADER wrong k %d breaks index", j); \
3572 return NULL; \
3573 } \
3574 assert (k >= 0 && k < (int)lline->num_breaks)
3575
3576 CHK_points;
3577 lline->points[j].y = pair->value.d;
3578 LOG_TRACE ("%s.leaders[].lines[%d].points[%d].y = %f [BD %d]\n",
3579 obj->name, i, j, pair->value.d, pair->code);
3580 break;
3581 case 30:
3582 CHK_points;
3583 lline->points[j].z = pair->value.d;
3584 LOG_TRACE ("%s.leaders[].lines[%d].points[%d].z = %f [BD %d]\n",
3585 obj->name, i, j, pair->value.d, pair->code);
3586 break;
3587 case 11:
3588 CHK_points;
3589 k++;
3590 lline->num_breaks = k + 1;
3591 lline->breaks = (Dwg_LEADER_Break *)realloc (
3592 lline->breaks, (k + 1) * sizeof (Dwg_LEADER_Break));
3593 memset (&ctx->leaders[k], 0, sizeof (Dwg_LEADER_Break));
3594 lline->breaks[k].start.x = pair->value.d;
3595 LOG_TRACE (
3596 "%s.leaders[].lines[%d].breaks[%d].start.x = %f [3BD %d]\n",
3597 obj->name, i, k, pair->value.d, pair->code);
3598 break;
3599 case 21:
3600 CHK_breaks;
3601 lline->breaks[k].start.y = pair->value.d;
3602 LOG_TRACE (
3603 "%s.leaders[].lines[%d].breaks[%d].start.y = %f [3BD %d]\n",
3604 obj->name, i, k, pair->value.d, pair->code);
3605 break;
3606 case 31:
3607 CHK_breaks;
3608 lline->breaks[k].start.z = pair->value.d;
3609 LOG_TRACE (
3610 "%s.leaders[].lines[%d].breaks[%d].start.z = %f [3BD %d]\n",
3611 obj->name, i, k, pair->value.d, pair->code);
3612 break;
3613 case 12:
3614 CHK_breaks;
3615 lline->breaks[k].end.x = pair->value.d;
3616 LOG_TRACE (
3617 "%s.leaders[].lines[%d].breaks[%d].end.x = %f [3BD %d]\n",
3618 obj->name, i, k, pair->value.d, pair->code);
3619 break;
3620 case 22:
3621 CHK_breaks;
3622 lline->breaks[k].end.y = pair->value.d;
3623 LOG_TRACE (
3624 "%s.leaders[].lines[%d].breaks[%d].end.y = %f [3BD %d]\n",
3625 obj->name, i, k, pair->value.d, pair->code);
3626 break;
3627 case 32:
3628 CHK_breaks;
3629 lline->breaks[k].end.z = pair->value.d;
3630 LOG_TRACE (
3631 "%s.leaders[].lines[%d].breaks[%d].end.z = %f [3BD %d]\n",
3632 obj->name, i, k, pair->value.d, pair->code);
3633 break;
3634 case 91:
3635 lline->line_index = pair->value.u;
3636 LOG_TRACE ("%s.leaders[].lines[%d].line_index = %u [BL %d]\n",
3637 obj->name, i, pair->value.u, pair->code);
3638 break;
3639 case 170:
3640 lline->type = pair->value.i;
3641 LOG_TRACE ("%s.leaders[].lines[%d].line_index = %d [BS %d]\n",
3642 obj->name, i, pair->value.i, pair->code);
3643 break;
3644 case 92:
3645 if (pair->value.u > 256)
3646 {
3647 lline->color.index = 256;
3648 lline->color.rgb = pair->value.u;
3649 lline->color.method = pair->value.u >> 0x18;
3650 LOG_TRACE (
3651 "%s.leaders[].lines[%d].color.rgb = %08X [CMC %d]\n",
3652 obj->name, i, pair->value.u, pair->code);
3653 }
3654 else
3655 {
3656 lline->color.index = pair->value.i;
3657 LOG_TRACE (
3658 "%s.leaders[].lines[%d].color.index = %d [CMC %d]\n",
3659 obj->name, i, pair->value.i, pair->code);
3660 }
3661 break;
3662 case 171:
3663 lline->linewt = dxf_find_lweight (pair->value.i);
3664 LOG_TRACE ("%s.leaders[].lines[%d].linewt = %d [BL %d]\n",
3665 obj->name, i, lline->linewt, pair->code);
3666 break;
3667 case 40:
3668 lline->arrow_size = pair->value.d;
3669 LOG_TRACE ("%s.leaders[].lines[%d].arrow_size = %f [BD %d]\n",
3670 obj->name, i, pair->value.d, pair->code);
3671 break;
3672 case 93:
3673 lline->flags = pair->value.i;
3674 LOG_TRACE ("%s.leaders[].lines[%d].line_index = %d [BL %d]\n",
3675 obj->name, i, pair->value.i, pair->code);
3676 break;
3677 case 305: // end
3678 break;
3679 default:
3680 LOG_ERROR (
3681 "Unknown DXF code %d for MULTILEADER.leaders[].lines[%d]",
3682 pair->code, i);
3683 return pair;
3684 }
3685 }
3686 }
3687 if (!lnode->num_lines)
3688 {
3689 free (lnode->lines);
3690 lnode->lines = NULL;
3691 }
3692 return pair;
3693 }
3694
3695 #undef CHK_points
3696 #undef CHK_breaks
3697
3698 static Dxf_Pair *
add_MULTILEADER_leaders(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)3699 add_MULTILEADER_leaders (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
3700 Dxf_Pair *restrict pair)
3701 {
3702 Dwg_Entity_MULTILEADER *o = obj->tio.entity->tio.MULTILEADER;
3703 if (pair != NULL && pair->code == 302 && strEQc (pair->value.s, "LEADER{"))
3704 {
3705 int i = -1, j = -1;
3706 Dwg_MLEADER_AnnotContext *ctx = &o->ctx;
3707 ctx->num_leaders = 0;
3708 while (pair != NULL && pair->code != 303 && pair->code != 0)
3709 {
3710 Dwg_LEADER_Node *lnode = i >= 0 ? &ctx->leaders[i] : NULL;
3711 dxf_free_pair (pair);
3712 pair = dxf_read_pair (dat);
3713 if (!pair)
3714 return NULL;
3715 if (!lnode && pair->code != 290 && pair->code != 304
3716 && pair->code != 303)
3717 {
3718 LOG_ERROR ("Missing MULTILEADER.LEADER{ 290 start");
3719 return pair;
3720 }
3721 if (lnode)
3722 lnode->num_breaks = 0;
3723 switch (pair->code)
3724 {
3725 case 290:
3726 i++;
3727 ctx->num_leaders = i + 1;
3728 LOG_TRACE ("%s.ctx.num_leaders = %d\n", obj->name, i + 1);
3729 ctx->leaders = (Dwg_LEADER_Node *)realloc (
3730 ctx->leaders, (i + 1) * sizeof (Dwg_LEADER_Node));
3731 if (!ctx->leaders)
3732 return NULL;
3733 memset (&ctx->leaders[i], 0, sizeof (Dwg_LEADER_Node));
3734 ctx->leaders[i].has_lastleaderlinepoint = pair->value.i;
3735 LOG_TRACE (
3736 "%s.ctx.leaders[%d].has_lastleaderlinepoint = %d [B %d]\n",
3737 obj->name, i, pair->value.i, pair->code);
3738 break;
3739 case 291:
3740 lnode->has_dogleg = pair->value.i;
3741 LOG_TRACE ("%s.ctx.leaders[%d].has_dogleg = %d [B %d]\n",
3742 obj->name, i, pair->value.i, pair->code);
3743 break;
3744 case 90:
3745 lnode->branch_index = pair->value.u;
3746 LOG_TRACE ("%s.ctx.leaders[%d].branch_index = %u [BL %d]\n",
3747 obj->name, i, pair->value.u, pair->code);
3748 break;
3749 case 271:
3750 lnode->attach_dir = pair->value.i;
3751 LOG_TRACE ("%s.ctx.leaders[%d].branch_index = %d [BS %d]\n",
3752 obj->name, i, pair->value.i, pair->code);
3753 break;
3754 case 40:
3755 lnode->dogleg_length = pair->value.d;
3756 LOG_TRACE ("%s.ctx.leaders[%d].dogleg_length = %f [BD %d]\n",
3757 obj->name, i, pair->value.d, pair->code);
3758 break;
3759 case 10:
3760 lnode->lastleaderlinepoint.x = pair->value.d;
3761 LOG_TRACE (
3762 "%s.ctx.leaders[%d].lastleaderlinepoint.x = %f [3BD %d]\n",
3763 obj->name, i, pair->value.d, pair->code);
3764 break;
3765 case 20:
3766 lnode->lastleaderlinepoint.y = pair->value.d;
3767 LOG_TRACE (
3768 "%s.ctx.leaders[%d].lastleaderlinepoint.y = %f [3BD %d]\n",
3769 obj->name, i, pair->value.d, pair->code);
3770 break;
3771 case 30:
3772 lnode->lastleaderlinepoint.z = pair->value.d;
3773 LOG_TRACE (
3774 "%s.ctx.leaders[%d].lastleaderlinepoint.z = %f [BD %d]\n",
3775 obj->name, i, pair->value.d, pair->code);
3776 break;
3777 case 11:
3778 if (lnode->has_dogleg)
3779 {
3780 lnode->dogleg_vector.x = pair->value.d;
3781 LOG_TRACE (
3782 "%s.ctx.leaders[%d].dogleg_vector.x = %f [3BD %d]\n",
3783 obj->name, i, pair->value.d, pair->code);
3784 }
3785 else
3786 {
3787 j++;
3788 lnode->num_breaks = j + 1;
3789 LOG_TRACE ("%s.leaders[%d].num_breaks = %d\n", obj->name, i,
3790 j + 1);
3791 lnode->breaks = (Dwg_LEADER_Break *)realloc (
3792 lnode->breaks, (j + 1) * sizeof (Dwg_LEADER_Break));
3793 lnode->breaks[j].start.x = pair->value.d;
3794 LOG_TRACE (
3795 "%s.ctx.leaders[%d].breaks[%d].start.x = %f [3BD %d]\n",
3796 obj->name, i, j, pair->value.d, pair->code);
3797 }
3798 break;
3799 case 21:
3800 if (lnode->has_dogleg)
3801 {
3802 lnode->dogleg_vector.y = pair->value.d;
3803 LOG_TRACE (
3804 "%s.ctx.leaders[%d].dogleg_vector.y = %f [3BD %d]\n",
3805 obj->name, i, pair->value.d, pair->code);
3806 }
3807 else
3808 {
3809 #define CHK_breaks \
3810 if (j < 0 || j >= (int)lnode->num_breaks) \
3811 return NULL; \
3812 assert (j >= 0 && j < (int)lnode->num_breaks)
3813
3814 CHK_breaks;
3815 lnode->breaks[j].start.y = pair->value.d;
3816 LOG_TRACE (
3817 "%s.ctx.leaders[%d].breaks[%d].start.y = %f [3BD %d]\n",
3818 obj->name, i, j, pair->value.d, pair->code);
3819 }
3820 break;
3821 case 31:
3822 if (lnode->has_dogleg)
3823 {
3824 lnode->dogleg_vector.z = pair->value.d;
3825 LOG_TRACE (
3826 "%s.ctx.leaders[%d].dogleg_vector.z = %f [3BD %d]\n",
3827 obj->name, i, pair->value.d, pair->code);
3828 }
3829 else
3830 {
3831 CHK_breaks;
3832 lnode->breaks[j].start.z = pair->value.d;
3833 LOG_TRACE (
3834 "%s.ctx.leaders[%d].breaks[%d].start.z = %f [3BD %d]\n",
3835 obj->name, i, j, pair->value.d, pair->code);
3836 }
3837 break;
3838 case 12:
3839 CHK_breaks;
3840 lnode->breaks[j].end.x = pair->value.d;
3841 LOG_TRACE ("%s.ctx.leaders[%d].breaks[%d].end.x = %f [3BD %d]\n",
3842 obj->name, i, j, pair->value.d, pair->code);
3843 break;
3844 case 22:
3845 CHK_breaks;
3846 lnode->breaks[j].end.y = pair->value.d;
3847 LOG_TRACE ("%s.ctx.leaders[%d].breaks[%d].end.y = %f [3BD %d]\n",
3848 obj->name, i, j, pair->value.d, pair->code);
3849 break;
3850 case 32:
3851 CHK_breaks;
3852 lnode->breaks[j].end.z = pair->value.d;
3853 LOG_TRACE ("%s.ctx.leaders[%d].breaks[%d].end.z = %f [3BD %d]\n",
3854 obj->name, i, j, pair->value.d, pair->code);
3855 break;
3856 case 304:
3857 if (strEQc (pair->value.s, "LEADER_LINE{"))
3858 pair = add_MULTILEADER_lines (obj, dat, pair, lnode);
3859 break;
3860 case 303: // end
3861 break;
3862 default:
3863 LOG_ERROR ("Unknown DXF code %d for MULTILEADER.leaders[]",
3864 pair->code);
3865 return pair;
3866 }
3867 }
3868 }
3869 return pair;
3870 }
3871 #undef CHK_breaks
3872
3873 static Dxf_Pair *
add_MULTILEADER(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)3874 add_MULTILEADER (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
3875 Dxf_Pair *restrict pair)
3876 {
3877 Dwg_Entity_MULTILEADER *o = obj->tio.entity->tio.MULTILEADER;
3878 int i = -1, j = -1;
3879
3880 if (pair->code == 300 && strEQc (pair->value.s, "CONTEXT_DATA{"))
3881 {
3882 // const Dwg_DYNAPI_field *fields
3883 // = dwg_dynapi_subclass_fields ("MLEADER_AnnotContext");
3884 Dwg_MLEADER_AnnotContext *ctx = &o->ctx;
3885 while (pair != NULL && pair->code != 301 && pair->code != 0)
3886 {
3887 switch (pair->code)
3888 {
3889 case 300:
3890 break;
3891 case 40:
3892 ctx->scale_factor = pair->value.d;
3893 LOG_TRACE ("%s.ctx.scale = %f [BD %d]\n", obj->name,
3894 pair->value.d, pair->code);
3895 break;
3896 case 10:
3897 ctx->content_base.x = pair->value.d;
3898 break;
3899 case 20:
3900 ctx->content_base.y = pair->value.d;
3901 break;
3902 case 30:
3903 ctx->content_base.z = pair->value.d;
3904 LOG_TRACE ("%s.ctx.content_base = (%f, %f, %f) [10 3BD]\n",
3905 obj->name, ctx->content_base.x, ctx->content_base.y,
3906 ctx->content_base.z);
3907 break;
3908 case 41:
3909 ctx->text_height = pair->value.d;
3910 LOG_TRACE ("%s.ctx.text_height = %f [BD %d]\n", obj->name,
3911 pair->value.d, pair->code);
3912 break;
3913 case 140:
3914 ctx->arrow_size = pair->value.d;
3915 LOG_TRACE ("%s.ctx.arrow_size = %f [BD %d]\n", obj->name,
3916 pair->value.d, pair->code);
3917 break;
3918 case 145:
3919 ctx->landing_gap = pair->value.d;
3920 LOG_TRACE ("%s.ctx.landing_gap = %f [BD %d]\n", obj->name,
3921 pair->value.d, pair->code);
3922 break;
3923 case 174:
3924 ctx->text_left = pair->value.i;
3925 LOG_TRACE ("%s.ctx.text_left = %d [BS %d]\n", obj->name,
3926 pair->value.i, pair->code);
3927 break;
3928 case 175:
3929 ctx->text_right = pair->value.i;
3930 LOG_TRACE ("%s.ctx.text_right = %d [BS %d]\n", obj->name,
3931 pair->value.i, pair->code);
3932 break;
3933 case 176:
3934 ctx->text_angletype = pair->value.i;
3935 LOG_TRACE ("%s.ctx.text_angletype = %d [BS %d]\n", obj->name,
3936 pair->value.i, pair->code);
3937 break;
3938 case 177:
3939 ctx->text_alignment = pair->value.i;
3940 LOG_TRACE ("%s.ctx.text_alignment = %d [BS %d]\n", obj->name,
3941 pair->value.i, pair->code);
3942 break;
3943 case 290:
3944 if (ctx->has_content_blk)
3945 goto unknown_mleader;
3946 ctx->has_content_txt = pair->value.i;
3947 LOG_TRACE ("%s.ctx.has_content_txt = %d [B %d]\n", obj->name,
3948 pair->value.i, pair->code);
3949 break;
3950 case 302:
3951 if (strEQc (pair->value.s, "LEADER{"))
3952 pair = add_MULTILEADER_leaders (obj, dat, pair);
3953 break;
3954 case 304:
3955 if (ctx->has_content_txt)
3956 {
3957 if (ctx->has_content_blk)
3958 goto unknown_mleader;
3959 if (dat->version >= R_2007)
3960 ctx->content.txt.default_text
3961 = (char *)bit_utf8_to_TU (pair->value.s, 0);
3962 else
3963 ctx->content.txt.default_text = strdup (pair->value.s);
3964 LOG_TRACE ("%s.ctx.content.txt.default_text = %s [%d T]\n",
3965 obj->name, pair->value.s, pair->code);
3966 }
3967 break;
3968 case 340:
3969 if (ctx->has_content_txt)
3970 {
3971 if (ctx->has_content_blk)
3972 goto unknown_mleader;
3973 ctx->content.txt.style
3974 = dwg_add_handleref (obj->parent, 5, pair->value.u, obj);
3975 LOG_TRACE ("%s.ctx.content.txt.style = " FORMAT_REF
3976 " [%d H]\n",
3977 obj->name, ARGS_REF (ctx->content.txt.style),
3978 pair->code);
3979 }
3980 break;
3981 case 11:
3982 if (!ctx->has_content_txt)
3983 goto unknown_mleader;
3984 ctx->content.txt.normal.x = pair->value.d;
3985 break;
3986 case 21:
3987 if (!ctx->has_content_txt)
3988 goto unknown_mleader;
3989 ctx->content.txt.normal.y = pair->value.d;
3990 break;
3991 case 31:
3992 if (!ctx->has_content_txt)
3993 goto unknown_mleader;
3994 ctx->content.txt.normal.z = pair->value.d;
3995 LOG_TRACE ("%s.ctx.content.txt.normal = (%f, %f, %f) [11 3BD]\n",
3996 obj->name, ctx->content.txt.normal.x,
3997 ctx->content.txt.normal.y, ctx->content.txt.normal.z);
3998 break;
3999 case 12:
4000 if (!ctx->has_content_txt)
4001 goto unknown_mleader;
4002 ctx->content.txt.location.x = pair->value.d;
4003 break;
4004 case 22:
4005 if (!ctx->has_content_txt)
4006 goto unknown_mleader;
4007 ctx->content.txt.location.y = pair->value.d;
4008 break;
4009 case 32:
4010 if (!ctx->has_content_txt)
4011 goto unknown_mleader;
4012 ctx->content.txt.location.z = pair->value.d;
4013 LOG_TRACE (
4014 "%s.ctx.content.txt.location = (%f, %f, %f) [12 3BD]\n",
4015 obj->name, ctx->content.txt.location.x,
4016 ctx->content.txt.location.y, ctx->content.txt.location.z);
4017 break;
4018 case 13:
4019 if (!ctx->has_content_txt)
4020 goto unknown_mleader;
4021 ctx->content.txt.direction.x = pair->value.d;
4022 break;
4023 case 23:
4024 if (!ctx->has_content_txt)
4025 goto unknown_mleader;
4026 ctx->content.txt.direction.y = pair->value.d;
4027 break;
4028 case 33:
4029 if (!ctx->has_content_txt)
4030 goto unknown_mleader;
4031 ctx->content.txt.direction.z = pair->value.d;
4032 LOG_TRACE (
4033 "%s.ctx.content.txt.direction = (%f, %f, %f) [13 3BD]\n",
4034 obj->name, ctx->content.txt.direction.x,
4035 ctx->content.txt.direction.y, ctx->content.txt.direction.z);
4036 break;
4037 case 42:
4038 if (!ctx->has_content_txt)
4039 goto unknown_mleader;
4040 ctx->content.txt.rotation = deg2rad (pair->value.d);
4041 LOG_TRACE ("%s.ctx.content.txt.rotation = %f [BD %d]\n",
4042 obj->name, ctx->content.txt.rotation, pair->code);
4043 break;
4044 case 43:
4045 if (!ctx->has_content_txt)
4046 goto unknown_mleader;
4047 ctx->content.txt.width = pair->value.d;
4048 LOG_TRACE ("%s.ctx.content.txt.width = %f [BD %d]\n", obj->name,
4049 pair->value.d, pair->code);
4050 break;
4051 case 44:
4052 if (!ctx->has_content_txt)
4053 goto unknown_mleader;
4054 ctx->content.txt.height = pair->value.d;
4055 LOG_TRACE ("%s.ctx.content.txt.height = %f [BD %d]\n", obj->name,
4056 pair->value.d, pair->code);
4057 break;
4058 case 45:
4059 if (!ctx->has_content_txt)
4060 goto unknown_mleader;
4061 ctx->content.txt.line_spacing_factor = pair->value.d;
4062 LOG_TRACE (
4063 "%s.ctx.content.txt.line_spacing_factor = %f [BD %d]\n",
4064 obj->name, pair->value.d, pair->code);
4065 break;
4066 case 170:
4067 if (!ctx->has_content_txt)
4068 goto unknown_mleader;
4069 ctx->content.txt.line_spacing_style = pair->value.i;
4070 LOG_TRACE (
4071 "%s.ctx.content.txt.line_spacing_style = %d [BS %d]\n",
4072 obj->name, pair->value.i, pair->code);
4073 break;
4074 case 171:
4075 if (!ctx->has_content_txt)
4076 goto unknown_mleader;
4077 ctx->content.txt.alignment = pair->value.i;
4078 LOG_TRACE ("%s.ctx.content.txt.alignment = %d [BS %d]\n",
4079 obj->name, pair->value.i, pair->code);
4080 break;
4081 case 172:
4082 if (!ctx->has_content_txt)
4083 break;
4084 ctx->content.txt.flow = pair->value.i;
4085 LOG_TRACE ("%s.ctx.content.txt.flow = %d [BS %d]\n", obj->name,
4086 pair->value.i, pair->code);
4087 break;
4088 case 90:
4089 if (!ctx->has_content_txt)
4090 goto unknown_mleader;
4091 ctx->content.txt.color.index = pair->value.i;
4092 LOG_TRACE ("%s.ctx.content.txt.color.index = %d [BS %d]\n",
4093 obj->name, pair->value.i, pair->code);
4094 break;
4095 case 91:
4096 if (!ctx->has_content_txt)
4097 goto unknown_mleader;
4098 ctx->content.txt.bg_color.index = pair->value.i;
4099 LOG_TRACE ("%s.ctx.content.txt.bg_color.index = %d [BS %d]\n",
4100 obj->name, pair->value.i, pair->code);
4101 break;
4102 case 141:
4103 if (!ctx->has_content_txt)
4104 goto unknown_mleader;
4105 ctx->content.txt.bg_scale = pair->value.d;
4106 LOG_TRACE ("%s.ctx.content.txt.bg_scale = %f [BD %d]\n",
4107 obj->name, pair->value.d, pair->code);
4108 break;
4109 case 142:
4110 if (!ctx->has_content_txt)
4111 goto unknown_mleader;
4112 ctx->content.txt.col_width = pair->value.d;
4113 LOG_TRACE ("%s.ctx.content.txt.col_width = %f [BD %d]\n",
4114 obj->name, pair->value.d, pair->code);
4115 break;
4116 case 143:
4117 if (!ctx->has_content_txt)
4118 goto unknown_mleader;
4119 ctx->content.txt.col_gutter = pair->value.d;
4120 LOG_TRACE ("%s.ctx.content.txt.col_gutter = %f [BD %d]\n",
4121 obj->name, pair->value.d, pair->code);
4122 break;
4123 case 92:
4124 if (!ctx->has_content_txt)
4125 goto unknown_mleader;
4126 ctx->content.txt.bg_transparency = pair->value.u;
4127 LOG_TRACE ("%s.ctx.content.txt.bg_transparency = %u [BL %d]\n",
4128 obj->name, pair->value.u, pair->code);
4129 break;
4130 case 291:
4131 if (!ctx->has_content_txt)
4132 goto unknown_mleader;
4133 ctx->content.txt.is_bg_fill = pair->value.i;
4134 LOG_TRACE ("%s.ctx.content.txt.is_bg_fill = %i [B %d]\n",
4135 obj->name, pair->value.i, pair->code);
4136 break;
4137 case 292:
4138 if (!ctx->has_content_txt)
4139 goto unknown_mleader;
4140 ctx->content.txt.is_bg_mask_fill = pair->value.i;
4141 LOG_TRACE ("%s.ctx.content.txt.is_bg_mask_fill = %i [B %d]\n",
4142 obj->name, pair->value.i, pair->code);
4143 break;
4144 case 293:
4145 if (!ctx->has_content_txt)
4146 goto unknown_mleader;
4147 ctx->content.txt.is_height_auto = pair->value.i;
4148 LOG_TRACE ("%s.ctx.content.txt.is_height_auto = %i [B %d]\n",
4149 obj->name, pair->value.i, pair->code);
4150 break;
4151 case 294:
4152 if (!ctx->has_content_txt)
4153 goto unknown_mleader;
4154 ctx->content.txt.is_col_flow_reversed = pair->value.i;
4155 LOG_TRACE (
4156 "%s.ctx.content.txt.is_col_flow_reversed = %i [B %d]\n",
4157 obj->name, pair->value.i, pair->code);
4158 break;
4159 case 295:
4160 if (!ctx->has_content_txt)
4161 goto unknown_mleader;
4162 ctx->content.txt.word_break = pair->value.i;
4163 LOG_TRACE ("%s.ctx.content.txt.word_break = %i [B %d]\n",
4164 obj->name, pair->value.i, pair->code);
4165 break;
4166 case 173:
4167 if (!ctx->has_content_txt)
4168 goto unknown_mleader;
4169 ctx->content.txt.col_type = pair->value.i;
4170 LOG_TRACE ("%s.ctx.content.txt.col_type = %d [BS %d]\n",
4171 obj->name, pair->value.i, pair->code);
4172 break;
4173 case 144:
4174 if (!ctx->has_content_txt)
4175 goto unknown_mleader;
4176 i++;
4177 ctx->content.txt.num_col_sizes = i + 1;
4178 ctx->content.txt.col_sizes = (double *)realloc (
4179 ctx->content.txt.col_sizes, (i + 1) * sizeof (double));
4180 ctx->content.txt.col_sizes[i] = pair->value.d;
4181 LOG_TRACE ("%s.ctx.content.txt.col_sizes[%d] = %f [BD %d]\n",
4182 obj->name, i, pair->value.d, pair->code);
4183 break;
4184 case 296:
4185 ctx->has_content_blk = pair->value.i;
4186 LOG_TRACE ("%s.ctx.has_content_blk = %i [B %d]\n", obj->name,
4187 pair->value.i, pair->code);
4188 break;
4189 case 14: // has_block
4190 if (!ctx->has_content_blk)
4191 goto unknown_mleader;
4192 ctx->content.blk.normal.x = pair->value.d;
4193 LOG_TRACE ("%s.ctx.content.blk.normal.x = %f [3BD %d]\n",
4194 obj->name, pair->value.d, pair->code);
4195 break;
4196 case 24:
4197 if (!ctx->has_content_blk)
4198 goto unknown_mleader;
4199 ctx->content.blk.normal.y = pair->value.d;
4200 LOG_TRACE ("%s.ctx.content.blk.normal.y = %f [3BD %d]\n",
4201 obj->name, pair->value.d, pair->code);
4202 break;
4203 case 34:
4204 if (!ctx->has_content_blk)
4205 goto unknown_mleader;
4206 ctx->content.blk.normal.z = pair->value.d;
4207 LOG_TRACE ("%s.ctx.content.blk.normal.z = %f [3BD %d]\n",
4208 obj->name, pair->value.d, pair->code);
4209 break;
4210 case 341:
4211 if (!ctx->has_content_blk)
4212 goto unknown_mleader;
4213 ctx->content.blk.block_table
4214 = dwg_add_handleref (obj->parent, 4, pair->value.u, obj);
4215 LOG_TRACE ("%s.ctx.content.blk.block_table = " FORMAT_REF
4216 " [%d H]\n",
4217 obj->name, ARGS_REF (ctx->content.blk.block_table),
4218 pair->code);
4219 break;
4220 case 15: // has_block
4221 if (!ctx->has_content_blk)
4222 goto unknown_mleader;
4223 ctx->content.blk.normal.x = pair->value.d;
4224 LOG_TRACE ("%s.ctx.content.blk.normal.x = %f [3BD %d]\n",
4225 obj->name, pair->value.d, pair->code);
4226 break;
4227 case 25:
4228 if (!ctx->has_content_blk)
4229 goto unknown_mleader;
4230 ctx->content.blk.location.y = pair->value.d;
4231 break;
4232 case 35:
4233 if (!ctx->has_content_blk)
4234 goto unknown_mleader;
4235 ctx->content.blk.location.z = pair->value.d;
4236 LOG_TRACE (
4237 "%s.ctx.content.blk.location = (%f, %f, %f) [3BD %d]\n",
4238 obj->name, ctx->content.blk.location.x,
4239 ctx->content.blk.location.y, ctx->content.blk.location.z,
4240 pair->code);
4241 break;
4242 case 16: // has_block
4243 if (!ctx->has_content_blk)
4244 goto unknown_mleader;
4245 ctx->content.blk.scale.x = pair->value.d;
4246 break;
4247 case 26:
4248 if (!ctx->has_content_blk)
4249 goto unknown_mleader;
4250 ctx->content.blk.scale.y = pair->value.d;
4251 break;
4252 case 36:
4253 if (!ctx->has_content_blk)
4254 goto unknown_mleader;
4255 ctx->content.blk.scale.z = pair->value.d;
4256 LOG_TRACE ("%s.ctx.content.blk.scale = (%f, %f, %f) [3BD %d]\n",
4257 obj->name, ctx->content.blk.scale.x,
4258 ctx->content.blk.scale.y, ctx->content.blk.scale.z,
4259 pair->code);
4260 break;
4261 case 46:
4262 if (!ctx->has_content_blk)
4263 goto unknown_mleader;
4264 ctx->content.blk.rotation = deg2rad (pair->value.d);
4265 LOG_TRACE ("%s.ctx.content.blk.rotation = %f [BD %d]\n",
4266 obj->name, pair->value.d, pair->code);
4267 break;
4268 case 93:
4269 if (!ctx->has_content_blk)
4270 goto unknown_mleader;
4271 if (pair->value.u > 257)
4272 {
4273 ctx->content.blk.color.index = 256;
4274 ctx->content.blk.color.rgb = pair->value.u;
4275 ctx->content.blk.color.method = pair->value.u >> 0x18;
4276 LOG_TRACE (
4277 "%s.leaders[].lines[%d].color.rgb = %08X [CMC %d]\n",
4278 obj->name, i, pair->value.u, pair->code);
4279 }
4280 else
4281 {
4282 ctx->content.blk.color.index = pair->value.i;
4283 if (pair->value.i == 257)
4284 {
4285 ctx->content.blk.color.method = 0xc8;
4286 ctx->content.blk.color.rgb = 0xc8000000;
4287 }
4288 LOG_TRACE (
4289 "%s.leaders[].lines[%d].color.index = %d [CMC %d]\n",
4290 obj->name, i, pair->value.i, pair->code);
4291 }
4292 break;
4293 case 47:
4294 if (!ctx->has_content_blk)
4295 goto unknown_mleader;
4296 j++;
4297 if (!j)
4298 {
4299 ctx->content.blk.transform
4300 = (double *)xcalloc (16, sizeof (double));
4301 if (!ctx->content.blk.transform)
4302 {
4303 return NULL;
4304 }
4305 }
4306 ctx->content.blk.transform[j] = pair->value.d;
4307 LOG_TRACE ("%s.ctx.content.blk.transform[%d] = %f [BD %d]\n",
4308 obj->name, j, pair->value.d, pair->code);
4309 break;
4310 case 110:
4311 ctx->base.x = pair->value.d;
4312 break;
4313 case 120:
4314 ctx->base.y = pair->value.d;
4315 break;
4316 case 130:
4317 ctx->base.z = pair->value.d;
4318 LOG_TRACE ("%s.ctx.base = (%f, %f, %f) [3BD %d]\n", obj->name,
4319 ctx->base.x, ctx->base.y, ctx->base.z, pair->code);
4320 break;
4321 case 111:
4322 ctx->base_dir.x = pair->value.d;
4323 break;
4324 case 121:
4325 ctx->base_dir.y = pair->value.d;
4326 break;
4327 case 131:
4328 ctx->base_dir.z = pair->value.d;
4329 LOG_TRACE ("%s.ctx.base = (%f, %f, %f) [3BD %d]\n", obj->name,
4330 ctx->base_dir.x, ctx->base_dir.y, ctx->base_dir.z,
4331 pair->code);
4332 break;
4333 case 112:
4334 ctx->base_vert.x = pair->value.d;
4335 break;
4336 case 122:
4337 ctx->base_vert.y = pair->value.d;
4338 break;
4339 case 132:
4340 ctx->base_vert.z = pair->value.d;
4341 LOG_TRACE ("%s.ctx.base = (%f, %f, %f) [3BD %d]\n", obj->name,
4342 ctx->base_vert.x, ctx->base_vert.y, ctx->base_vert.z,
4343 pair->code);
4344 break;
4345 case 297:
4346 ctx->is_normal_reversed = pair->value.i;
4347 LOG_TRACE ("%s.ctx.is_normal_reversed = %i [B %d]\n", obj->name,
4348 pair->value.i, pair->code);
4349 break;
4350 case 273:
4351 ctx->text_top = pair->value.i;
4352 LOG_TRACE ("%s.ctx.text_top = %i [BS %d]\n", obj->name,
4353 pair->value.i, pair->code);
4354 break;
4355 case 272:
4356 ctx->text_bottom = pair->value.i;
4357 LOG_TRACE ("%s.ctx.text_bottom = %i [BS %d]\n", obj->name,
4358 pair->value.i, pair->code);
4359 break;
4360
4361 case 301: // end ctx
4362 return pair;
4363 default:
4364 unknown_mleader:
4365 LOG_ERROR ("Unknown DXF code %d for %s", pair->code,
4366 "MULTILEADER");
4367 }
4368 dxf_free_pair (pair);
4369 pair = dxf_read_pair (dat);
4370 }
4371 }
4372 return pair;
4373 }
4374
4375 // returns with pair if not found, or NULL on error.
4376 // only for geomesh_pts (num 93, 13, 14) and geomesh_faces (num 96, 97-99)
4377 static Dxf_Pair *
add_GEODATA(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)4378 add_GEODATA (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
4379 Dxf_Pair *restrict pair)
4380 {
4381 Dwg_Data *dwg = obj->parent;
4382 Dwg_Object_GEODATA *o = obj->tio.object->tio.GEODATA;
4383 int i = -1;
4384
4385 while (pair != NULL)
4386 {
4387 switch (pair->code)
4388 {
4389 case 93:
4390 i = -1;
4391 o->num_geomesh_pts = pair->value.u;
4392 o->geomesh_pts = (Dwg_GEODATA_meshpt *)xcalloc (
4393 pair->value.u, sizeof (Dwg_GEODATA_meshpt));
4394 if (!o->geomesh_pts && o->num_geomesh_pts)
4395 return NULL;
4396 LOG_TRACE ("%s.num_geomesh_pts = %u [BL %d]\n", obj->name,
4397 pair->value.u, pair->code);
4398 break;
4399 case 96:
4400 i = -1;
4401 o->num_geomesh_faces = pair->value.u;
4402 o->geomesh_faces = (Dwg_GEODATA_meshface *)xcalloc (
4403 pair->value.u, sizeof (Dwg_GEODATA_meshface));
4404 if (!o->geomesh_faces && o->num_geomesh_faces)
4405 return NULL;
4406 LOG_TRACE ("%s.num_geomesh_faces = %u [BL %d]\n", obj->name,
4407 pair->value.u, pair->code);
4408 break;
4409 case 13:
4410 i++;
4411 #define CHK_geomesh_pts \
4412 if (i < 0 || i >= (int)o->num_geomesh_pts || !o->geomesh_pts) \
4413 return NULL; \
4414 assert (i >= 0 && i < (int)o->num_geomesh_pts)
4415
4416 CHK_geomesh_pts;
4417 o->geomesh_pts[i].source_pt.x = pair->value.d;
4418 break;
4419 case 23:
4420 CHK_geomesh_pts;
4421 o->geomesh_pts[i].source_pt.y = pair->value.d;
4422 LOG_TRACE ("%s.geomesh_pts[%d] = (%f, %f) [2RD %d]\n", obj->name, i,
4423 o->geomesh_pts[i].source_pt.x, pair->value.d, 13);
4424 break;
4425 case 14:
4426 i++;
4427 CHK_geomesh_pts;
4428 o->geomesh_pts[i].dest_pt.x = pair->value.d;
4429 break;
4430 case 24:
4431 CHK_geomesh_pts;
4432 o->geomesh_pts[i].dest_pt.y = pair->value.d;
4433 LOG_TRACE ("%s.geomesh_pts[%d].dest_pt = (%f, %f) [2RD %d]\n",
4434 obj->name, i, o->geomesh_pts[i].dest_pt.x, pair->value.d,
4435 13);
4436 break;
4437 case 97:
4438 i++;
4439 #define CHK_geomesh_faces \
4440 if (i < 0 || i >= (int)o->num_geomesh_faces || !o->geomesh_faces) \
4441 return NULL; \
4442 assert (o->geomesh_faces); \
4443 assert (i >= 0 && i < (int)o->num_geomesh_faces)
4444
4445 CHK_geomesh_faces;
4446 o->geomesh_faces[i].face1 = pair->value.u;
4447 break;
4448 case 98:
4449 CHK_geomesh_faces;
4450 o->geomesh_faces[i].face2 = pair->value.u;
4451 break;
4452 case 99:
4453 CHK_geomesh_faces;
4454 o->geomesh_faces[i].face3 = pair->value.u;
4455 LOG_TRACE ("%s.geomesh_faces[%d] = (%u, %u, %u) [3*BL %d]\n",
4456 obj->name, i, o->geomesh_faces[i].face1,
4457 o->geomesh_faces[i].face2, pair->value.u, 97);
4458 break;
4459 case 0:
4460 default:
4461 return pair;
4462 }
4463 dxf_free_pair (pair);
4464 pair = dxf_read_pair (dat);
4465 }
4466 return pair;
4467 }
4468 #undef CHK_geomesh_pts
4469 #undef CHK_geomesh_faces
4470
4471 // returns with 0
4472 // subclass for multiple objects.
4473 // Only handle conflicts?, codes with multiple keys.
4474 // 1, 309
4475 static Dxf_Pair *
add_CellStyle(Dwg_Object * restrict obj,Dwg_CellStyle * o,const char * key,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)4476 add_CellStyle (Dwg_Object *restrict obj, Dwg_CellStyle *o, const char *key,
4477 Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
4478 {
4479 Dwg_Data *dwg = obj->parent;
4480 BITCODE_H hdl;
4481 enum
4482 {
4483 NONE,
4484 TABLEFORMAT,
4485 CONTENTFORMAT,
4486 CELLMARGIN,
4487 GRIDFORMAT,
4488 CELLSTYLE
4489 } mode;
4490 int i = -1, j = -1;
4491 int grid = -1;
4492 mode = NONE;
4493
4494 while (pair != NULL && pair->code != 0)
4495 {
4496 switch (pair->code)
4497 {
4498 case 0:
4499 break;
4500 case 1:
4501 if (strEQc (pair->value.s, "TABLEFORMAT_BEGIN"))
4502 mode = TABLEFORMAT;
4503 else if (strEQc (pair->value.s, "CONTENTFORMAT_BEGIN"))
4504 mode = CONTENTFORMAT;
4505 else if (strEQc (pair->value.s, "CELLMARGIN_BEGIN"))
4506 mode = CELLMARGIN;
4507 else if (strEQc (pair->value.s, "GRIDFORMAT_BEGIN"))
4508 mode = GRIDFORMAT;
4509 else if (strEQc (pair->value.s, "CELLSTYLE_BEGIN"))
4510 {
4511 dxf_free_pair (pair);
4512 return dxf_read_pair (dat);
4513 }
4514 else
4515 goto unknown_default;
4516 break;
4517 case 300:
4518 if (mode == CONTENTFORMAT)
4519 {
4520 if (obj->parent->header.version >= R_2007)
4521 o->content_format.value_format_string
4522 = (BITCODE_T)bit_utf8_to_TU (pair->value.s, 0);
4523 else
4524 o->content_format.value_format_string = strdup (pair->value.s);
4525 LOG_TRACE (
4526 "%s.%s.content_format.value_format_string = \"%s\" [T %d]\n",
4527 obj->name, key, pair->value.s, pair->code);
4528 }
4529 else if (mode == TABLEFORMAT)
4530 {
4531 if (!strEQc (pair->value.s, "CONTENTFORMAT"))
4532 goto unknown_default;
4533 }
4534 else if (mode == CELLSTYLE)
4535 return pair;
4536 else
4537 goto unknown_default;
4538 break;
4539 case 301:
4540 // ignore MARGIN
4541 if (!strEQc (pair->value.s, "MARGIN"))
4542 goto unknown_default;
4543 break;
4544 case 302:
4545 // ignore GRIDFORMAT
4546 if (!strEQc (pair->value.s, "GRIDFORMAT"))
4547 goto unknown_default;
4548 break;
4549 case 309:
4550 if (strEQc (pair->value.s, "TABLEFORMAT_END")
4551 || strEQc (pair->value.s, "CELLSTYLE_END"))
4552 mode = NONE;
4553 else if (strEQc (pair->value.s, "CONTENTFORMAT_END")
4554 || strEQc (pair->value.s, "CELLMARGIN_END")
4555 || strEQc (pair->value.s, "GRIDFORMAT_END"))
4556 mode = TABLEFORMAT;
4557 else
4558 goto unknown_default;
4559 break;
4560 case 90:
4561 if (mode == TABLEFORMAT)
4562 {
4563 o->type = pair->value.u;
4564 LOG_TRACE ("%s.%s.type = " FORMAT_BL " [BL %d]\n", obj->name,
4565 key, pair->value.u, pair->code);
4566 }
4567 else if (mode == CONTENTFORMAT)
4568 {
4569 o->content_format.property_override_flags = pair->value.u;
4570 LOG_TRACE (
4571 "%s.%s.content_format.property_override_flags = " FORMAT_BLx
4572 " [BLx %d]\n",
4573 obj->name, key, pair->value.u, pair->code);
4574 }
4575 else if (mode == GRIDFORMAT)
4576 {
4577 if (grid < 0 || grid >= (int)o->num_borders)
4578 return NULL;
4579 o->borders[grid].border_overrides = pair->value.u;
4580 LOG_TRACE ("%s.%s.borders[%d].border_overrides = " FORMAT_BLx
4581 " [BLx %d]\n",
4582 obj->name, key, grid, pair->value.u, pair->code);
4583 }
4584 else if (mode == CELLSTYLE)
4585 return pair;
4586 else if (mode == NONE)
4587 return pair;
4588 else
4589 goto unknown_default;
4590 break;
4591 case 91:
4592 if (mode == TABLEFORMAT)
4593 {
4594 o->property_override_flags = pair->value.u;
4595 LOG_TRACE ("%s.%s.property_override_flags = " FORMAT_BLx
4596 " [BLx %d]\n",
4597 obj->name, key, pair->value.u, pair->code);
4598 }
4599 else if (mode == CONTENTFORMAT)
4600 {
4601 o->content_format.property_flags = pair->value.u;
4602 LOG_TRACE ("%s.%s.content_format.property_flags = " FORMAT_BLx
4603 " [BLx %d]\n",
4604 obj->name, key, pair->value.u, pair->code);
4605 }
4606 else if (mode == GRIDFORMAT)
4607 {
4608 if (grid < 0 || grid >= (int)o->num_borders)
4609 return NULL;
4610 o->borders[grid].border_type = pair->value.u;
4611 LOG_TRACE ("%s.%s.borders[%d].border_type = " FORMAT_BLx
4612 " [BLx %d]\n",
4613 obj->name, key, grid, pair->value.u, pair->code);
4614 }
4615 else if (mode == CELLSTYLE)
4616 return pair;
4617 else if (mode == NONE)
4618 return pair;
4619 else
4620 goto unknown_default;
4621 break;
4622 case 92:
4623 if (mode == TABLEFORMAT)
4624 {
4625 o->merge_flags = pair->value.u;
4626 LOG_TRACE ("%s.%s.merge_flags = " FORMAT_BLx " [BLx %d]\n",
4627 obj->name, key, pair->value.u, pair->code);
4628 }
4629 else if (mode == CONTENTFORMAT)
4630 {
4631 o->content_format.value_data_type = pair->value.u;
4632 LOG_TRACE ("%s.%s.content_format.value_data_type = " FORMAT_BLx
4633 " [BLx %d]\n",
4634 obj->name, key, pair->value.u, pair->code);
4635 }
4636 else if (mode == GRIDFORMAT)
4637 {
4638 if (grid < 0 || grid >= (int)o->num_borders)
4639 return NULL;
4640 o->borders[grid].linewt = pair->value.i;
4641 LOG_TRACE ("%s.%s.borders[%d].linewt = %d [BSd %d]\n", obj->name,
4642 key, grid, pair->value.i, pair->code);
4643 }
4644 else
4645 goto unknown_default;
4646 break;
4647 case 93:
4648 if (mode == TABLEFORMAT)
4649 {
4650 o->content_layout = pair->value.u;
4651 LOG_TRACE ("%s.%s.content_layout = " FORMAT_BL " [BL %d]\n",
4652 obj->name, key, pair->value.u, pair->code);
4653 }
4654 else if (mode == CONTENTFORMAT)
4655 {
4656 o->content_format.value_unit_type = pair->value.u;
4657 LOG_TRACE ("%s.%s.content_format.value_unit_type = " FORMAT_BLx
4658 " [BLx %d]\n",
4659 obj->name, key, pair->value.u, pair->code);
4660 }
4661 else if (mode == GRIDFORMAT)
4662 {
4663 if (grid < 0 || grid >= (int)o->num_borders)
4664 return NULL;
4665 o->borders[grid].visible = pair->value.i;
4666 LOG_TRACE ("%s.%s.borders[%d].visible = %d [BL %d]\n", obj->name,
4667 key, grid, pair->value.i, pair->code);
4668 }
4669 else
4670 goto unknown_default;
4671 break;
4672 case 94:
4673 if (mode == TABLEFORMAT)
4674 {
4675 o->num_borders = pair->value.u;
4676 j = 0;
4677 LOG_TRACE ("%s.%s.num_borders = " FORMAT_BL " [BL %d]\n",
4678 obj->name, key, pair->value.u, pair->code);
4679 o->borders = (Dwg_GridFormat *)xcalloc (o->num_borders,
4680 sizeof (Dwg_GridFormat));
4681 }
4682 else if (mode == CONTENTFORMAT)
4683 {
4684 o->content_format.cell_alignment = pair->value.u;
4685 LOG_TRACE ("%s.%s.content_format.cell_alignment = " FORMAT_BL
4686 " [BL %d]\n",
4687 obj->name, key, pair->value.u, pair->code);
4688 }
4689 else
4690 goto unknown_default;
4691 break;
4692 case 95:
4693 if (mode == TABLEFORMAT)
4694 {
4695 grid++;
4696 if (grid < 0 || grid >= (int)o->num_borders)
4697 return NULL;
4698 o->borders[grid].index_mask = pair->value.u;
4699 LOG_TRACE ("%s.%s.borders[%d].index_mask = " FORMAT_BLx
4700 " [BLx %d]\n",
4701 obj->name, key, grid, pair->value.u, pair->code);
4702 }
4703 else
4704 goto unknown_default;
4705 break;
4706 case 62:
4707 if (mode == TABLEFORMAT)
4708 {
4709 o->bg_color.rgb = pair->value.u;
4710 o->bg_color.method = pair->value.u >> 0x18;
4711 if (pair->value.u == 257)
4712 {
4713 o->bg_color.method = 0xc8;
4714 o->bg_color.rgb = 0xc8000000;
4715 }
4716 else
4717 o->bg_color.index = dwg_find_color_index (pair->value.u);
4718 LOG_TRACE ("%s.%s.bg_color = %08x [CMTC %d]\n", obj->name, key,
4719 pair->value.u, pair->code);
4720 }
4721 else if (mode == CONTENTFORMAT)
4722 {
4723 o->content_format.content_color.rgb = pair->value.u;
4724 o->content_format.content_color.method = pair->value.u >> 0x18;
4725 if (pair->value.u == 257)
4726 {
4727 o->content_format.content_color.method = 0xc8;
4728 o->content_format.content_color.rgb = 0xc8000000;
4729 }
4730 else
4731 o->content_format.content_color.index
4732 = dwg_find_color_index (pair->value.u);
4733 LOG_TRACE (
4734 "%s.%s.content_format.content_color = %08x [CMTC %d]\n",
4735 obj->name, key, pair->value.u, pair->code);
4736 }
4737 else if (mode == GRIDFORMAT)
4738 {
4739 if (grid < 0 || grid >= (int)o->num_borders)
4740 return NULL;
4741 o->borders[grid].color.rgb = pair->value.d;
4742 o->borders[grid].color.method = pair->value.u >> 0x18;
4743 if (pair->value.u == 257)
4744 {
4745 o->borders[grid].color.method = 0xc8;
4746 o->borders[grid].color.rgb = 0xc8000000;
4747 }
4748 else
4749 o->borders[grid].color.index
4750 = dwg_find_color_index (pair->value.u);
4751 LOG_TRACE ("%s.%s.borders[%d].color = %08x [CMTC %d]\n",
4752 obj->name, key, grid, pair->value.u, pair->code);
4753 }
4754 else
4755 goto unknown_default;
4756 break;
4757 case 40:
4758 if (mode == CELLMARGIN)
4759 {
4760 i++;
4761 switch (i)
4762 {
4763 case 0:
4764 o->vert_margin = pair->value.d;
4765 LOG_TRACE ("%s.%s.vert_margin = %f [BD %d]\n", obj->name,
4766 key, pair->value.d, pair->code);
4767 break;
4768 case 1:
4769 o->horiz_margin = pair->value.d;
4770 LOG_TRACE ("%s.%s.horiz_margin = %f [BD %d]\n", obj->name,
4771 key, pair->value.d, pair->code);
4772 break;
4773 case 2:
4774 o->bottom_margin = pair->value.d;
4775 LOG_TRACE ("%s.%s.bottom_margin = %f [BD %d]\n", obj->name,
4776 key, pair->value.d, pair->code);
4777 break;
4778 case 3:
4779 o->right_margin = pair->value.d;
4780 LOG_TRACE ("%s.%s.right_margin = %f [BD %d]\n", obj->name,
4781 key, pair->value.d, pair->code);
4782 break;
4783 case 4:
4784 o->margin_horiz_spacing = pair->value.d;
4785 LOG_TRACE ("%s.%s.margin_horiz_spacing = %f [BD %d]\n",
4786 obj->name, key, pair->value.d, pair->code);
4787 break;
4788 case 5:
4789 o->margin_vert_spacing = pair->value.d;
4790 LOG_TRACE ("%s.%s.margin_vert_spacing = %f [BD %d]\n",
4791 obj->name, key, pair->value.d, pair->code);
4792 break;
4793 default:
4794 LOG_ERROR ("Invalid CELLMARGIN 40 index %d", i);
4795 goto unknown_default;
4796 }
4797 }
4798 else if (mode == CONTENTFORMAT)
4799 {
4800 o->content_format.rotation = pair->value.d;
4801 LOG_TRACE ("%s.%s.content_format.rotation = %f [BD %d]\n",
4802 obj->name, key, pair->value.d, pair->code);
4803 }
4804 else if (mode == GRIDFORMAT)
4805 {
4806 if (grid < 0 || grid >= (int)o->num_borders)
4807 return NULL;
4808 o->borders[grid].double_line_spacing = pair->value.d;
4809 LOG_TRACE (
4810 "%s.%s.borders[%d].double_line_spacing = %f [BD %d]\n",
4811 obj->name, key, grid, pair->value.d, pair->code);
4812 }
4813 else
4814 goto unknown_default;
4815 break;
4816 case 140:
4817 if (mode == CONTENTFORMAT)
4818 {
4819 o->content_format.block_scale = pair->value.d;
4820 LOG_TRACE ("%s.%s.content_format.block_scale = %f [BD %d]\n",
4821 obj->name, key, pair->value.d, pair->code);
4822 }
4823 else
4824 goto unknown_default;
4825 break;
4826 case 144:
4827 if (mode == CONTENTFORMAT)
4828 {
4829 o->content_format.text_height = pair->value.d;
4830 LOG_TRACE ("%s.%s.content_format.text_height = %f [BD %d]\n",
4831 obj->name, key, pair->value.d, pair->code);
4832 }
4833 else
4834 goto unknown_default;
4835 break;
4836 case 170:
4837 if (mode == TABLEFORMAT)
4838 {
4839 o->data_flags = pair->value.u;
4840 LOG_TRACE ("%s.%s.data_flags = " FORMAT_BSx " [BSx %d]\n",
4841 obj->name, key, pair->value.i, pair->code);
4842 }
4843 else
4844 goto unknown_default;
4845 break;
4846 case 171:
4847 if (mode == TABLEFORMAT)
4848 {
4849 o->margin_override_flags = pair->value.u;
4850 LOG_TRACE ("%s.%s.margin_override_flags = " FORMAT_BSx
4851 " [BSx %d]\n",
4852 obj->name, key, pair->value.u, pair->code);
4853 }
4854 else
4855 goto unknown_default;
4856 break;
4857 case 340:
4858 if (mode == CONTENTFORMAT)
4859 {
4860 o->content_format.text_style
4861 = dwg_add_handleref (dwg, 3, pair->value.u, NULL);
4862 LOG_TRACE ("%s.%s.content_format.text_style = " FORMAT_REF
4863 " [H 3 %d]\n",
4864 obj->name, key,
4865 ARGS_REF (o->content_format.text_style), pair->code);
4866 }
4867 else if (mode == GRIDFORMAT)
4868 {
4869 if (grid < 0 || grid >= (int)o->num_borders)
4870 return NULL;
4871 o->borders[grid].ltype
4872 = dwg_add_handleref (dwg, 3, pair->value.u, NULL);
4873 LOG_TRACE ("%s.%s.borders[%d].ltype = " FORMAT_REF " [H 3 %d]\n",
4874 obj->name, key, grid,
4875 ARGS_REF (o->borders[grid].ltype), pair->code);
4876 }
4877 else
4878 goto unknown_default;
4879 break;
4880 /*
4881 case 7:
4882 hdl = find_tablehandle (dwg, pair);
4883 assert (hdl);
4884 CHK_array (i, rowstyles);
4885 o->rowstyles[i].text_style = hdl;
4886 LOG_TRACE ("%s.rowstyles[%d].text_style = " FORMAT_REF " [H %d]\n",
4887 obj->name, i, ARGS_REF(hdl), pair->code);
4888 break;
4889 case 1:
4890 CHK_array (i, rowstyles);
4891 o->rowstyles[i].format_string = bit_utf8_to_TU (pair->value.s, 0);
4892 LOG_TRACE ("%s.rowstyles[%d].format_string = %s [TU %d]\n",
4893 obj->name, i, pair->value.s, pair->code);
4894 break;
4895 */
4896 default:
4897 unknown_default:
4898 LOG_ERROR ("Unknown DXF code %d for %s.%s", pair->code, obj->name,
4899 key);
4900 }
4901 dxf_free_pair (pair);
4902 pair = dxf_read_pair (dat);
4903 }
4904 return pair;
4905 }
4906
4907 // returns with 0
4908 static Dxf_Pair *
add_TABLESTYLE(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)4909 add_TABLESTYLE (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
4910 Dxf_Pair *restrict pair)
4911 {
4912 Dwg_Data *dwg = obj->parent;
4913 Dwg_Object_TABLESTYLE *o = obj->tio.object->tio.TABLESTYLE;
4914 BITCODE_H hdl;
4915 int i = -1, j = -1;
4916
4917 #define CHK_rowstyles \
4918 if (!(i >= 0 && i < 3) || !o->num_rowstyles || !o->rowstyles) \
4919 return NULL; \
4920 assert (i >= 0 && i < 3); \
4921 assert (o->num_rowstyles); \
4922 assert (o->rowstyles)
4923
4924 #define CHK_borders \
4925 if (!(j >= 0 && j <= 6) || !o->rowstyles[i].num_borders \
4926 || !o->rowstyles[i].borders) \
4927 return NULL; \
4928 assert (j >= 0 && j < 6); \
4929 assert (o->rowstyles[i].num_borders); \
4930 assert (o->rowstyles[i].borders)
4931
4932 while (pair != NULL && pair->code != 0)
4933 {
4934 switch (pair->code)
4935 {
4936 case 0:
4937 break;
4938 case 7:
4939 i++;
4940 CHK_rowstyles;
4941 hdl = find_tablehandle (dwg, pair);
4942 if (!hdl)
4943 return NULL;
4944 assert (hdl);
4945 o->rowstyles[i].text_style = hdl;
4946 LOG_TRACE ("%s.rowstyles[%d].text_style = " FORMAT_REF " [H %d]\n",
4947 obj->name, i, ARGS_REF (hdl), pair->code);
4948 break;
4949 case 140:
4950 CHK_rowstyles;
4951 o->rowstyles[i].text_height = pair->value.d;
4952 LOG_TRACE ("%s.rowstyles[%d].text_height = %f [BD %d]\n", obj->name,
4953 i, pair->value.d, pair->code);
4954 break;
4955 case 170:
4956 CHK_rowstyles;
4957 o->rowstyles[i].text_alignment = pair->value.i;
4958 LOG_TRACE ("%s.rowstyles[%d].text_alignment = " FORMAT_BS
4959 " [BS %d]\n",
4960 obj->name, i, o->rowstyles[i].text_alignment, pair->code);
4961 break;
4962 case 62:
4963 CHK_rowstyles;
4964 o->rowstyles[i].text_color.index = pair->value.i;
4965 // TODO rgb with 420
4966 LOG_TRACE ("%s.rowstyles[%d].text_color.index = %d [CMC %d]\n",
4967 obj->name, i, pair->value.i, pair->code);
4968 break;
4969 case 63:
4970 CHK_rowstyles;
4971 o->rowstyles[i].fill_color.index = pair->value.i;
4972 LOG_TRACE ("%s.rowstyles[%d].fill_color.index = %d [CMC %d]\n",
4973 obj->name, i, pair->value.i, pair->code);
4974 break;
4975 case 283:
4976 CHK_rowstyles;
4977 o->rowstyles[i].has_bgcolor = pair->value.i;
4978 LOG_TRACE ("%s.rowstyles[%d].has_bgcolor = %d [B %d]\n", obj->name,
4979 i, pair->value.i, pair->code);
4980 break;
4981 case 90:
4982 CHK_rowstyles;
4983 o->rowstyles[i].data_type = pair->value.i;
4984 LOG_TRACE ("%s.rowstyles[%d].data_type = %d [BL %d]\n", obj->name, i,
4985 pair->value.i, pair->code);
4986 break;
4987 case 91:
4988 CHK_rowstyles;
4989 o->rowstyles[i].unit_type = pair->value.i;
4990 LOG_TRACE ("%s.rowstyles[%d].unit_type = %d [BL %d]\n", obj->name, i,
4991 pair->value.i, pair->code);
4992 break;
4993 case 1:
4994 CHK_rowstyles;
4995 o->rowstyles[i].format_string = bit_utf8_to_TU (pair->value.s, 0);
4996 LOG_TRACE ("%s.rowstyles[%d].format_string = %s [TU %d]\n",
4997 obj->name, i, pair->value.s, pair->code);
4998 break;
4999 case 274:
5000 case 275:
5001 case 276:
5002 case 277:
5003 case 278:
5004 case 279:
5005 CHK_rowstyles;
5006 j = pair->code - 274;
5007 if (j < 0 || j >= 6)
5008 return NULL;
5009 assert (j >= 0 && j <= 6);
5010 if (!o->rowstyles[i].borders)
5011 {
5012 o->rowstyles[i].borders = (Dwg_TABLESTYLE_border *)xcalloc (
5013 6, sizeof (Dwg_TABLESTYLE_border));
5014 if (!o->rowstyles[i].borders)
5015 {
5016 o->rowstyles[i].num_borders = 0;
5017 return NULL;
5018 }
5019 o->rowstyles[i].num_borders = 6;
5020 }
5021 CHK_borders;
5022 assert (o->rowstyles[i].num_borders);
5023 o->rowstyles[i].borders[j].linewt = dxf_find_lweight (pair->value.i);
5024 LOG_TRACE ("%s.rowstyles[%d].borders[%d].linewt = %d [BSd %d]\n",
5025 obj->name, i, j, o->rowstyles[i].borders[j].linewt,
5026 pair->code);
5027 break;
5028 case 284:
5029 case 285:
5030 case 286:
5031 case 287:
5032 case 288:
5033 case 289:
5034 CHK_rowstyles;
5035 j = pair->code - 284;
5036 CHK_borders;
5037 o->rowstyles[i].borders[j].visible = pair->value.i;
5038 LOG_TRACE ("%s.rowstyles[%d].borders[%d].visible = %d [B %d]\n",
5039 obj->name, i, j, pair->value.i, pair->code);
5040 break;
5041 case 64:
5042 case 65:
5043 case 66:
5044 case 67:
5045 case 68:
5046 case 69:
5047 CHK_rowstyles;
5048 j = pair->code - 64;
5049 CHK_borders;
5050 assert (j >= 0 && j <= 6);
5051 o->rowstyles[i].borders[j].color.index = pair->value.i;
5052 LOG_TRACE (
5053 "%s.rowstyles[%d].borders[%d].color.index = %d [CMC %d]\n",
5054 obj->name, i, j, pair->value.i, pair->code);
5055 break;
5056 default:
5057 if (is_type_stable (obj->fixedtype))
5058 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "TABLESTYLE")
5059 else
5060 LOG_WARN ("Unknown DXF code %d for %s", pair->code, "TABLESTYLE");
5061 }
5062 dxf_free_pair (pair);
5063 pair = dxf_read_pair (dat);
5064 }
5065 return pair;
5066 }
5067
5068 // returns with 0
5069 static Dxf_Pair *
add_TABLEGEOMETRY_Cell(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5070 add_TABLEGEOMETRY_Cell (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5071 Dxf_Pair *restrict pair)
5072 {
5073 Dwg_Data *dwg = obj->parent;
5074 Dwg_Object_TABLEGEOMETRY *o = obj->tio.object->tio.TABLEGEOMETRY;
5075 BITCODE_H hdl;
5076 BITCODE_BL num_cells = o->num_cells;
5077 int i = -1, j = -1;
5078
5079 o->cells = (Dwg_TABLEGEOMETRY_Cell *)xcalloc (
5080 num_cells, sizeof (Dwg_TABLEGEOMETRY_Cell));
5081 if (!o->cells)
5082 {
5083 o->num_cells = 0;
5084 return NULL;
5085 }
5086
5087 while (pair != NULL && pair->code != 0)
5088 {
5089 switch (pair->code)
5090 {
5091 case 0:
5092 break;
5093 case 93:
5094 i++; // the first
5095 #define CHK_cells \
5096 if (i < 0 || i >= (int)num_cells || !o->cells) \
5097 return NULL; \
5098 assert (i >= 0 && i < (int)num_cells); \
5099 assert (o->cells)
5100
5101 CHK_cells;
5102 o->cells[i].geom_data_flag = pair->value.i;
5103 LOG_TRACE ("%s.cells[%d].geom_data_flag = " FORMAT_BL " [BL %d]\n",
5104 obj->name, i, o->cells[i].geom_data_flag, pair->code);
5105 break;
5106 case 40:
5107 CHK_cells;
5108 o->cells[i].width_w_gap = pair->value.d;
5109 LOG_TRACE ("%s.cells[%d].width_w_gap = %f [BD %d]\n", obj->name, i,
5110 pair->value.d, pair->code);
5111 break;
5112 case 41:
5113 CHK_cells;
5114 o->cells[i].height_w_gap = pair->value.d;
5115 LOG_TRACE ("%s.cells[%d].height_w_gap = %f [BD %d]\n", obj->name, i,
5116 pair->value.d, pair->code);
5117 break;
5118 case 330:
5119 CHK_cells;
5120 hdl = find_tablehandle (dwg, pair);
5121 if (hdl)
5122 {
5123 if (hdl->handleref.code != 4) // turn the 5 into a 4
5124 o->cells[i].tablegeometry
5125 = dwg_add_handleref (dwg, 4, hdl->handleref.value, NULL);
5126 else
5127 o->cells[i].tablegeometry = hdl;
5128 }
5129 else
5130 o->cells[i].tablegeometry = dwg_add_handleref (dwg, 4, 0, NULL);
5131 LOG_TRACE ("%s.cells[%d].tablegeometry = " FORMAT_REF " [H %d]\n",
5132 obj->name, i, ARGS_REF (o->cells[i].tablegeometry),
5133 pair->code);
5134 break;
5135 case 94:
5136 CHK_cells;
5137 o->cells[i].num_geometry = pair->value.i;
5138 LOG_TRACE ("%s.cells[%d].num_geometry = " FORMAT_BL " [BL %d]\n",
5139 obj->name, i, o->cells[i].num_geometry, pair->code);
5140 o->cells[i].geometry = (Dwg_CellContentGeometry *)xcalloc (
5141 pair->value.i, sizeof (Dwg_CellContentGeometry));
5142 if (!o->cells[i].geometry)
5143 {
5144 o->cells[i].num_geometry = 0;
5145 return NULL;
5146 }
5147 j = -1;
5148 break;
5149 case 10:
5150 CHK_cells;
5151 j++;
5152
5153 #define CHK_geometry \
5154 if (j < 0 || j >= (int)o->cells[i].num_geometry || !o->cells[i].geometry) \
5155 return NULL; \
5156 assert (j >= 0 && j < (int)o->cells[i].num_geometry); \
5157 assert (o->cells[i].geometry)
5158
5159 CHK_geometry;
5160 o->cells[i].geometry[j].dist_top_left.x = pair->value.d;
5161 LOG_TRACE (
5162 "%s.cells[%d].geometry[%d].dist_top_left.x = %f [BD %d]\n",
5163 obj->name, i, j, pair->value.d, pair->code);
5164 break;
5165 case 20:
5166 CHK_cells;
5167 CHK_geometry;
5168 o->cells[i].geometry[j].dist_top_left.y = pair->value.d;
5169 break;
5170 case 30:
5171 CHK_cells;
5172 CHK_geometry;
5173 o->cells[i].geometry[j].dist_top_left.z = pair->value.d;
5174 LOG_TRACE ("%s.cells[%d].geometry[%d].dist_top_left = ( %f, %f, %f) "
5175 "[3BD 10]\n",
5176 obj->name, i, j, o->cells[i].geometry[j].dist_top_left.x,
5177 o->cells[i].geometry[j].dist_top_left.y, pair->value.d);
5178 break;
5179 case 11:
5180 CHK_cells;
5181 CHK_geometry;
5182 o->cells[i].geometry[j].dist_center.x = pair->value.d;
5183 LOG_TRACE ("%s.cells[%d].geometry[%d].dist_center.x = %f [BD %d]\n",
5184 obj->name, i, j, pair->value.d, pair->code);
5185 break;
5186 case 21:
5187 CHK_cells;
5188 CHK_geometry;
5189 o->cells[i].geometry[j].dist_center.y = pair->value.d;
5190 break;
5191 case 31:
5192 CHK_cells;
5193 CHK_geometry;
5194 o->cells[i].geometry[j].dist_center.z = pair->value.d;
5195 LOG_TRACE ("%s.cells[%d].geometry[%d].dist_center = ( %f, %f, %f) "
5196 "[3BD 10]\n",
5197 obj->name, i, j, o->cells[i].geometry[j].dist_center.x,
5198 o->cells[i].geometry[j].dist_center.y, pair->value.d);
5199 break;
5200 case 43:
5201 CHK_cells;
5202 CHK_geometry;
5203 o->cells[i].geometry[j].content_width = pair->value.d;
5204 LOG_TRACE ("%s.cells[%d].geometry[%d].content_width = %f [BD %d]\n",
5205 obj->name, i, j, pair->value.d, pair->code);
5206 break;
5207 case 44:
5208 CHK_cells;
5209 CHK_geometry;
5210 o->cells[i].geometry[j].content_height = pair->value.d;
5211 LOG_TRACE ("%s.cells[%d].geometry[%d].content_height = %f [BD %d]\n",
5212 obj->name, i, j, pair->value.d, pair->code);
5213 break;
5214 case 45:
5215 CHK_cells;
5216 CHK_geometry;
5217 o->cells[i].geometry[j].width = pair->value.d;
5218 LOG_TRACE ("%s.cells[%d].geometry[%d].width = %f [BD %d]\n",
5219 obj->name, i, j, pair->value.d, pair->code);
5220 break;
5221 case 46:
5222 CHK_cells;
5223 CHK_geometry;
5224 o->cells[i].geometry[j].height = pair->value.d;
5225 LOG_TRACE ("%s.cells[%d].geometry[%d].height = %f [BD %d]\n",
5226 obj->name, i, j, pair->value.d, pair->code);
5227 break;
5228 case 95:
5229 CHK_cells;
5230 CHK_geometry;
5231 o->cells[i].geometry[j].unknown = pair->value.i;
5232 LOG_TRACE ("%s.cells[%d].geometry[%d].unknown = %d [BL %d]\n",
5233 obj->name, i, j, pair->value.i, pair->code);
5234 break;
5235 default:
5236 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "TABLESTYLE");
5237 }
5238 dxf_free_pair (pair);
5239 pair = dxf_read_pair (dat);
5240 }
5241 return pair;
5242 }
5243
5244 #undef CHK_cells
5245 #undef CHK_geometry
5246
5247 // starts with 71 or 75
5248 static Dxf_Pair *
add_DIMASSOC(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5249 add_DIMASSOC (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5250 Dxf_Pair *restrict pair)
5251 {
5252 Dwg_Object_DIMASSOC *o = obj->tio.object->tio.DIMASSOC;
5253 Dwg_Data *dwg = obj->parent;
5254 int i = -1, j = -1;
5255 int have_rotated_type = 0;
5256 o->ref = (Dwg_DIMASSOC_Ref *)xcalloc (4, sizeof (Dwg_DIMASSOC_Ref));
5257 if (!o->ref)
5258 {
5259 return NULL;
5260 }
5261
5262 while (pair != NULL && pair->code != 0)
5263 {
5264 switch (pair->code)
5265 {
5266 case 0:
5267 break;
5268 case 71: // always before each ref
5269 i++;
5270 while (!(o->associativity & (1 << i)) && i < 4) // popcount x
5271 i++;
5272 if (!(i >= 0 && i <= 3))
5273 {
5274 LOG_ERROR ("Invalid DIMASSOC_Ref index %d", i)
5275 return pair;
5276 }
5277 o->rotated_type = pair->value.i;
5278 have_rotated_type = 1; // early bump
5279 LOG_TRACE ("%s.rotated_type = %d [BS %d]\n", obj->name,
5280 pair->value.i, pair->code);
5281 break;
5282 case 1:
5283 if (strNE (pair->value.s, "AcDbOsnapPointRef"))
5284 {
5285 LOG_ERROR ("Invalid DIMASSOC subclass %s", pair->value.s);
5286 return pair;
5287 }
5288 if (!(i >= 0 && i <= 3))
5289 {
5290 LOG_ERROR ("Invalid DIMASSOC_Ref index %d", i)
5291 return pair;
5292 }
5293 if (!have_rotated_type) // not already bumped
5294 {
5295 i++;
5296 while (!(o->associativity & (1 << i)) && i < 4) // popcount x
5297 i++;
5298 if (i > 3)
5299 i = 3;
5300 assert (i >= 0 && i <= 3);
5301 }
5302 o->ref[i].classname = dwg_add_u8_input (dwg, pair->value.s);
5303 LOG_TRACE ("%s.ref[%d].classname = %s [T %d]\n", obj->name, i,
5304 pair->value.s, pair->code);
5305 have_rotated_type = 0;
5306 break;
5307 case 72:
5308 if (i < 0 || i > 3)
5309 break;
5310 o->ref[i].osnap_type = pair->value.i;
5311 LOG_TRACE ("%s.ref[%d].osnap_type = %d [RC %d]\n", obj->name, i,
5312 pair->value.i, pair->code);
5313 break;
5314 // FIXME: 301 xrefpaths[j]
5315 case 331:
5316 {
5317 BITCODE_BS n;
5318 if (i < 0 || i > 3)
5319 break;
5320 n = o->ref[i].num_xrefs;
5321 o->ref[i].xrefs = (BITCODE_H *)realloc (
5322 o->ref[i].xrefs, (n + 1) * sizeof (BITCODE_H));
5323 o->ref[i].xrefs[n]
5324 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5325 LOG_TRACE ("%s.ref[%d].xrefs[%d] = " FORMAT_REF " [H* %d]\n",
5326 obj->name, i, n, ARGS_REF (o->ref[i].xrefs[n]),
5327 pair->code);
5328 o->ref[i].num_xrefs++;
5329 }
5330 break;
5331 case 74:
5332 if (i < 0 || i > 3)
5333 break;
5334 o->ref[i].num_intsectobj = pair->value.i;
5335 o->ref[i].intsectobj
5336 = (BITCODE_H *)xcalloc (pair->value.i, sizeof (BITCODE_H));
5337 j = 0;
5338 LOG_TRACE ("%s.ref[%d].num_intsectobj = %d [BS %d]\n", obj->name, i,
5339 pair->value.i, pair->code);
5340 break;
5341 case 332:
5342 if (i < 0 || j < 0 || i > 3 || j >= (int)o->ref[i].num_intsectobj)
5343 break;
5344 o->ref[i].intsectobj[j]
5345 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5346 LOG_TRACE ("%s.ref[%d].intsectobj[%d] = " FORMAT_REF " [H %d]\n",
5347 obj->name, i, j, ARGS_REF (o->ref[i].intsectobj[j]),
5348 pair->code);
5349 j++;
5350 break;
5351 case 73:
5352 if (i < 0)
5353 break;
5354 o->ref[i].main_subent_type = pair->value.i;
5355 LOG_TRACE ("%s.ref[%d].main_subent_type = %d [BS %d]\n", obj->name,
5356 i, pair->value.i, pair->code);
5357 break;
5358 case 75:
5359 if (i < 0)
5360 break;
5361 o->ref[i].has_lastpt_ref = pair->value.i;
5362 LOG_TRACE ("%s.ref[%d].has_lastpt_ref = %d [B %d]\n", obj->name, i,
5363 pair->value.i, pair->code);
5364 break;
5365 case 91:
5366 if (i < 0)
5367 break;
5368 o->ref[i].main_gsmarker = pair->value.i;
5369 LOG_TRACE ("%s.ref[%d].main_gsmarker = %d [BL %d]\n", obj->name, i,
5370 pair->value.i, pair->code);
5371 break;
5372 case 40:
5373 if (i < 0)
5374 break;
5375 o->ref[i].osnap_dist = pair->value.d;
5376 LOG_TRACE ("%s.ref[%d].osnap_dist = %f [BD %d]\n", obj->name, i,
5377 pair->value.d, pair->code);
5378 break;
5379 case 10:
5380 if (i < 0)
5381 break;
5382 o->ref[i].osnap_pt.x = pair->value.d;
5383 break;
5384 case 20:
5385 if (i < 0)
5386 break;
5387 o->ref[i].osnap_pt.y = pair->value.d;
5388 break;
5389 case 30:
5390 if (i < 0)
5391 break;
5392 o->ref[i].osnap_pt.z = pair->value.d;
5393 LOG_TRACE ("%s.ref[%d].osnap_pt = (%f, %f, %f) [3BD 10]\n",
5394 obj->name, i, o->ref[i].osnap_pt.x, o->ref[i].osnap_pt.y,
5395 pair->value.d);
5396 break;
5397 default:
5398 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "DIMASSOC");
5399 }
5400 dxf_free_pair (pair);
5401 pair = dxf_read_pair (dat);
5402 }
5403 return pair;
5404 }
5405
5406 // starting with 90 or 8
5407 static Dxf_Pair *
add_LAYER_entry(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5408 add_LAYER_entry (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5409 Dxf_Pair *restrict pair)
5410 {
5411 Dwg_Object_LAYER_INDEX *o = obj->tio.object->tio.LAYER_INDEX;
5412 Dwg_Data *dwg = obj->parent;
5413 int i = 0;
5414 o->entries = (Dwg_LAYER_entry *)xcalloc (1, sizeof (Dwg_LAYER_entry));
5415 o->num_entries = 1;
5416 if (!o->entries)
5417 {
5418 return NULL;
5419 }
5420 if (pair->code == 90 && !pair->value.i)
5421 {
5422 LOG_TRACE ("skip first %s.entries[%d].numlayers = %d [BL %d]\n",
5423 obj->name, i, pair->value.i, pair->code);
5424 dxf_free_pair (pair);
5425 pair = dxf_read_pair (dat);
5426 }
5427 while (pair != NULL && pair->code != 0)
5428 {
5429 switch (pair->code)
5430 {
5431 case 0:
5432 break;
5433 case 8:
5434 o->entries[i].name = dwg_add_u8_input (dwg, pair->value.s);
5435 LOG_TRACE ("%s.entries[%d].name = %s [T %d]\n", obj->name, i,
5436 pair->value.s, pair->code);
5437 break;
5438 case 360:
5439 o->entries[i].handle
5440 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5441 LOG_TRACE ("%s.entries[%d].handle = " FORMAT_REF " [H %d]\n",
5442 obj->name, i, ARGS_REF (o->entries[i].handle),
5443 pair->code);
5444 break;
5445 case 90:
5446 o->entries[i].numlayers = pair->value.i;
5447 LOG_TRACE ("%s.entries[%d].numlayers = %d [BL %d]\n", obj->name, i,
5448 pair->value.i, pair->code);
5449 o->num_entries++;
5450 i++;
5451 o->entries = (Dwg_LAYER_entry *)realloc (
5452 o->entries, o->num_entries * sizeof (Dwg_LAYER_entry));
5453 if (!o->entries)
5454 return NULL;
5455 break;
5456 default:
5457 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "LAYER_INDEX");
5458 return NULL;
5459 }
5460 dxf_free_pair (pair);
5461 pair = dxf_read_pair (dat);
5462 }
5463 o->num_entries--;
5464 LOG_TRACE ("%s.num_entries = %d [BL]\n", obj->name, o->num_entries);
5465 return pair;
5466 }
5467
5468 static Dxf_Pair *
add_EVALVARIANT(Dwg_Data * restrict dwg,Bit_Chain * restrict dat,Dwg_EvalVariant * value)5469 add_EVALVARIANT (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
5470 Dwg_EvalVariant *value)
5471 {
5472 Dxf_Pair *pair = dxf_read_pair (dat);
5473 EXPECT_DXF ("EvalVariant", code, 70);
5474 value->code = pair->value.i;
5475 LOG_TRACE ("%s.%s = %d [BL %d]\n", "EvalVariant", "code", pair->value.i,
5476 pair->code);
5477 dxf_free_pair (pair);
5478
5479 pair = dxf_read_pair (dat);
5480 if (!pair || pair->code == 0)
5481 return pair;
5482 switch (dwg_resbuf_value_type (pair->value.i))
5483 {
5484 case DWG_VT_REAL:
5485 value->u.bd = pair->value.d;
5486 LOG_TRACE ("%s.%s = %f [BD %d]\n", "EvalVariant", "value", pair->value.d,
5487 pair->code);
5488 break;
5489 case DWG_VT_INT32:
5490 value->u.bl = pair->value.u;
5491 LOG_TRACE ("%s.%s = %u [BL %d]\n", "EvalVariant", "value", pair->value.u,
5492 pair->code);
5493 break;
5494 case DWG_VT_INT16:
5495 value->u.bs = pair->value.i;
5496 LOG_TRACE ("%s.%s = %d [BS %d]\n", "EvalVariant", "value", pair->value.i,
5497 pair->code);
5498 break;
5499 case DWG_VT_INT8:
5500 value->u.rc = pair->value.i;
5501 LOG_TRACE ("%s.%s = %d [RC %d]\n", "EvalVariant", "value", pair->value.i,
5502 pair->code);
5503 break;
5504 case DWG_VT_STRING:
5505 value->u.text = dwg_add_u8_input (dwg, pair->value.s);
5506 LOG_TRACE ("%s.%s = %s [T %d]\n", "EvalVariant", "value", pair->value.s,
5507 pair->code);
5508 break;
5509 case DWG_VT_HANDLE:
5510 value->u.handle = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
5511 LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n", "EvalVariant", "value",
5512 ARGS_REF (value->u.handle), pair->code);
5513 break;
5514 case DWG_VT_BINARY:
5515 case DWG_VT_OBJECTID:
5516 case DWG_VT_POINT3D:
5517 case DWG_VT_INVALID:
5518 case DWG_VT_INT64:
5519 case DWG_VT_BOOL:
5520 default:
5521 LOG_ERROR ("Invalid EvalVariant.value.type %d", pair->code)
5522 break;
5523 }
5524 dxf_free_pair (pair);
5525 return NULL;
5526 }
5527
5528 static int
add_VALUEPARAMs(Dwg_Data * restrict dwg,Bit_Chain * restrict dat,Dwg_VALUEPARAM * value)5529 add_VALUEPARAMs (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
5530 Dwg_VALUEPARAM *value)
5531 {
5532 Dxf_Pair *pair = dxf_read_pair (dat);
5533 if (pair == NULL || pair->code != 90)
5534 {
5535 LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5536 "VALUEPARAM", pair ? pair->code : -1, 90, "class_version");
5537 return 0;
5538 }
5539 value->class_version = pair->value.u;
5540 LOG_TRACE ("%s.%s = %d [BL %d]\n", "VALUEPARAM", "class_version",
5541 pair->value.i, pair->code);
5542 dxf_free_pair (pair);
5543
5544 pair = dxf_read_pair (dat);
5545 if (pair == NULL || pair->code != 1)
5546 {
5547 LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5548 "VALUEPARAM", pair ? pair->code : -1, 1, "name");
5549 return 0;
5550 }
5551 value->name = dwg_add_u8_input (dwg, pair->value.s);
5552 LOG_TRACE ("%s.%s = %s [BL %d]\n", "VALUEPARAM", "name", pair->value.s,
5553 pair->code);
5554 dxf_free_pair (pair);
5555
5556 pair = dxf_read_pair (dat);
5557 if (pair == NULL || pair->code != 90)
5558 {
5559 LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5560 "VALUEPARAM", pair ? pair->code : -1, 90, "unit_type");
5561 return 0;
5562 }
5563 value->unit_type = pair->value.u;
5564 LOG_TRACE ("%s.%s = %d [BL %d]\n", "VALUEPARAM", "unit_type", pair->value.i,
5565 pair->code);
5566 dxf_free_pair (pair);
5567
5568 pair = dxf_read_pair (dat);
5569 if (pair == NULL || pair->code != 90)
5570 {
5571 LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5572 "VALUEPARAM", pair ? pair->code : -1, 90, "num_vars");
5573 return 0;
5574 }
5575 value->num_vars = pair->value.u;
5576 LOG_TRACE ("%s.%s = %d [BL %d]\n", "VALUEPARAM", "num_vars", pair->value.i,
5577 pair->code);
5578 value->vars = (Dwg_VALUEPARAM_vars*)xcalloc (value->num_vars,
5579 sizeof (Dwg_VALUEPARAM_vars));
5580 if (!value->vars)
5581 return 0;
5582 for (unsigned j = 0; j < value->num_vars; j++)
5583 {
5584 pair = add_EVALVARIANT (dwg, dat, &value->vars[j].value);
5585 if (pair)
5586 return 0;
5587 pair = dxf_read_pair (dat);
5588 if (pair == NULL || pair->code != 330)
5589 {
5590 LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5591 "VALUEPARAM", pair ? pair->code : -1, 330, "handle");
5592 return 0;
5593 }
5594 value->vars[j].handle = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
5595 LOG_TRACE ("%s.vars[%u].handle = " FORMAT_REF " [H %d]\n", "VALUEPARAM",
5596 j, ARGS_REF (value->vars[j].handle), pair->code);
5597 dxf_free_pair (pair);
5598 }
5599 return 1;
5600 }
5601
5602 static Dxf_Pair *
add_EVAL_Edge(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5603 add_EVAL_Edge (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5604 Dxf_Pair *restrict pair)
5605 {
5606 Dwg_Object_EVALUATION_GRAPH *o = obj->tio.object->tio.EVALUATION_GRAPH;
5607 Dwg_Data *dwg = obj->parent;
5608 int i = -1;
5609 o->edges = (Dwg_EVAL_Edge *)xcalloc (1, sizeof (Dwg_EVAL_Edge));
5610 o->num_edges = 0;
5611 if (!o->edges)
5612 return NULL;
5613
5614 while (pair != NULL && pair->code == 92)
5615 {
5616 i++;
5617 o->edges = (Dwg_EVAL_Edge *)realloc (o->edges, o->num_edges * sizeof (Dwg_EVAL_Edge));
5618 if (!o->edges)
5619 return NULL;
5620 o->num_edges++;
5621 o->edges[i].id = pair->value.i; // 92
5622 LOG_TRACE ("%s.edges[%d].id = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5623 dxf_free_pair (pair);
5624
5625 pair = dxf_read_pair (dat);
5626 if (!pair || pair->code != 93)
5627 {
5628 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5629 return pair;
5630 }
5631 o->edges[i].nextid = pair->value.i; // 93
5632 LOG_TRACE ("%s.edges[%d].nextid = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5633 dxf_free_pair (pair);
5634
5635 pair = dxf_read_pair (dat);
5636 if (!pair || pair->code != 94)
5637 {
5638 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5639 return pair;
5640 }
5641 o->edges[i].e1 = pair->value.i; // 94
5642 LOG_TRACE ("%s.edges[%d].e1 = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5643 dxf_free_pair (pair);
5644
5645 pair = dxf_read_pair (dat);
5646 if (!pair || pair->code != 91)
5647 {
5648 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5649 return pair;
5650 }
5651 o->edges[i].e2 = pair->value.i; // 91
5652 LOG_TRACE ("%s.edges[%d].e2 = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5653 dxf_free_pair (pair);
5654
5655 pair = dxf_read_pair (dat);
5656 if (!pair || pair->code != 91)
5657 {
5658 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5659 return pair;
5660 }
5661 o->edges[i].e3 = pair->value.i; // 91
5662 LOG_TRACE ("%s.edges[%d].e3 = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5663 dxf_free_pair (pair);
5664
5665 for (int j = 0; j < 5; j++)
5666 {
5667 pair = dxf_read_pair (dat);
5668 if (!pair || pair->code != 92)
5669 {
5670 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5671 return pair;
5672 }
5673 o->edges[i].out_edge[j] = pair->value.i; // 92
5674 LOG_TRACE ("%s.edges[%d].out_edge[%d] = %d [BL %d]\n", obj->name, i, j, pair->value.i, pair->code);
5675 dxf_free_pair (pair);
5676 }
5677
5678 pair = dxf_read_pair (dat);
5679 }
5680 LOG_TRACE ("%s.num_edges = %d [BL]\n", obj->name, o->num_edges);
5681 return pair;
5682 }
5683
5684 /* Starts with first AcDbEvalGraph 91. FIXME edges */
5685 static Dxf_Pair *
add_EVAL_Node(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5686 add_EVAL_Node (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5687 Dxf_Pair *restrict pair)
5688 {
5689 Dwg_Object_EVALUATION_GRAPH *o = obj->tio.object->tio.EVALUATION_GRAPH;
5690 Dwg_Data *dwg = obj->parent;
5691 int i = -1, j = 0;
5692 o->nodes = (Dwg_EVAL_Node *)xcalloc (1, sizeof (Dwg_EVAL_Node));
5693 o->num_nodes = 1;
5694 if (!o->nodes)
5695 {
5696 return NULL;
5697 }
5698 while (pair != NULL && pair->code != 0)
5699 {
5700 switch (pair->code)
5701 {
5702 case 91:
5703 i++;
5704 o->nodes = (Dwg_EVAL_Node *)realloc (o->nodes, (i + 1) * sizeof (Dwg_EVAL_Node));
5705 if (!o->nodes)
5706 break;
5707 o->num_nodes = i + 1;
5708 o->nodes[i].id = pair->value.i;
5709 LOG_TRACE ("%s.nodes[%d].id = %d [BL %d]\n", obj->name, i,
5710 pair->value.i, pair->code);
5711 break;
5712 case 93: // must be 32
5713 o->nodes[i].edge_flags = pair->value.i;
5714 LOG_TRACE ("%s.nodes[%d].edge_flags = %d [BL %d]\n", obj->name, i,
5715 pair->value.i, pair->code);
5716 break;
5717 case 95:
5718 o->nodes[i].edge_flags = pair->value.i;
5719 if (pair->value.i != 32)
5720 LOG_WARN ("%s.nodes[%d].edge_flags = %d [BL %d] != 32\n", obj->name, i,
5721 pair->value.i, pair->code)
5722 else
5723 LOG_TRACE ("%s.nodes[%d].edge_flags = %d [BL %d]\n", obj->name, i,
5724 pair->value.i, pair->code)
5725 break;
5726 case 360:
5727 o->nodes[i].evalexpr
5728 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5729 LOG_TRACE ("%s.nodes[%d].evalexpr = " FORMAT_REF " [H %d]\n",
5730 obj->name, i, ARGS_REF (o->nodes[i].evalexpr),
5731 pair->code);
5732 break;
5733 case 92:
5734 if (j > 3) // 0 - 3
5735 { // list of edges
5736 return add_EVAL_Edge (obj, dat, pair);
5737 }
5738 o->nodes[i].node[j] = pair->value.i;
5739 LOG_TRACE ("%s.nodes[%d].edge[%d] = %d [BL %d]\n", obj->name, i, j,
5740 pair->value.i, pair->code);
5741 j++;
5742 break;
5743 default:
5744 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5745 return NULL;
5746 }
5747 dxf_free_pair (pair);
5748 pair = dxf_read_pair (dat);
5749 }
5750 LOG_TRACE ("%s.num_nodes = %d [BL]\n", obj->name, o->num_nodes);
5751 return pair;
5752 }
5753
5754 static Dxf_Pair *
add_ASSOCNETWORK(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5755 add_ASSOCNETWORK (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5756 Dxf_Pair *restrict pair)
5757 {
5758 Dwg_Object_ASSOCNETWORK *o = obj->tio.object->tio.ASSOCNETWORK;
5759 Dwg_Data *dwg = obj->parent;
5760 BITCODE_BL num;
5761 BITCODE_H *hv = NULL;
5762 Dwg_ASSOCACTION_Deps *deps;
5763
5764 if (pair == NULL || pair->code != 90)
5765 return pair;
5766 EXPECT_INT_DXF ("network_version", 90, BS);
5767 FIELD_BL (network_action_index, 90);
5768 FIELD_BL (num_actions, 90);
5769 num = o->num_actions;
5770
5771 deps = (Dwg_ASSOCACTION_Deps*)xcalloc (num, sizeof (Dwg_ASSOCACTION_Deps));
5772 if (!deps)
5773 return NULL;
5774 for (unsigned i = 0; i < num; i++)
5775 {
5776 BITCODE_H hdl;
5777 int is_owned, code;
5778 pair = dxf_read_pair (dat);
5779 if (pair && (pair->code == 360 || pair->code == 330))
5780 deps[i].is_owned = pair->code == 360;
5781 else
5782 {
5783 LOG_ERROR ("Invalid ASSOCACTION.deps[%d].is_owned DXF code %d", i,
5784 pair ? pair->code : 0);
5785 return NULL;
5786 }
5787 code = deps[i].is_owned ? DWG_HDL_HARDOWN : DWG_HDL_SOFTPTR;
5788 deps[i].dep = dwg_add_handleref (dwg, code, pair->value.u, obj);
5789 LOG_TRACE ("%s.%s[%u] = " FORMAT_REF " [H %d]\n", obj->name, "deps", i,
5790 ARGS_REF (deps[i].dep), pair->code);
5791 dxf_free_pair (pair);
5792 }
5793 dwg_dynapi_entity_set_value (o, obj->name, "actions", &deps, 1);
5794
5795 pair = dxf_read_pair (dat);
5796 num = pair ? pair->value.u : 0;
5797 EXPECT_INT_DXF ("num_owned_actions", 90, BL);
5798 if (num)
5799 {
5800 hv = (BITCODE_H*)xcalloc (num, sizeof (BITCODE_H));
5801 if (!hv)
5802 return NULL;
5803 }
5804 for (unsigned i = 0; i < num; i++)
5805 {
5806 BITCODE_H hdl;
5807 pair = dxf_read_pair (dat);
5808 if (!pair || pair->code != 330)
5809 {
5810 LOG_ERROR ("Invalid ASSOCNETWORK.owned_actions[%d] DXF code %d", i,
5811 pair ? pair->code : 0);
5812 return NULL;
5813 }
5814 hdl = dwg_add_handleref (dwg, 3, pair->value.u, obj);
5815 LOG_TRACE ("%s.%s[%d] = " FORMAT_REF " [H %d]\n", obj->name,
5816 "owned_actions", i, ARGS_REF (hdl), pair->code);
5817 hv[i] = hdl;
5818 dxf_free_pair (pair);
5819 }
5820 if (num)
5821 dwg_dynapi_entity_set_value (o, obj->name, "owned_actions", &hv, 1);
5822 return NULL;
5823 }
5824
5825 // with ASSOC2DCONSTRAINTGROUP, ASSOCNETWORK, ASSOCACTION
5826 static Dxf_Pair *
add_ASSOCACTION(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5827 add_ASSOCACTION (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5828 Dxf_Pair *restrict pair)
5829 {
5830 Dwg_Object_ASSOCACTION *o = obj->tio.object->tio.ASSOCACTION;
5831 Dwg_Data *dwg = obj->parent;
5832 BITCODE_BL num;
5833 BITCODE_H *hv = NULL;
5834 Dwg_VALUEPARAM *values = NULL;
5835 Dwg_ASSOCACTION_Deps *deps;
5836 unsigned class_version;
5837
5838 if (pair == NULL || pair->code != 90)
5839 return pair;
5840 class_version = pair->value.u;
5841 EXPECT_INT_DXF ("class_version", 90, BS);
5842 FIELD_BL (geometry_status, 90);
5843 FIELD_HANDLE (owningnetwork, 4, 330);
5844 FIELD_HANDLE (actionbody, 3, 360);
5845 FIELD_BL (action_index, 90);
5846 FIELD_BL (max_assoc_dep_index, 90);
5847
5848 FIELD_BL (num_deps, 90);
5849 num = o->num_deps;
5850 deps = (Dwg_ASSOCACTION_Deps*)xcalloc (num, sizeof (Dwg_ASSOCACTION_Deps));
5851 if (!deps)
5852 return NULL;
5853 for (unsigned i = 0; i < num; i++)
5854 {
5855 BITCODE_H hdl;
5856 int is_owned, code;
5857 pair = dxf_read_pair (dat);
5858 if (pair && (pair->code == 360 || pair->code == 330))
5859 deps[i].is_owned = pair->code == 360;
5860 else
5861 {
5862 LOG_ERROR ("Invalid ASSOCACTION.deps[%d].is_owned DXF code %d", i,
5863 pair ? pair->code : 0);
5864 return NULL;
5865 }
5866 code = deps[i].is_owned ? DWG_HDL_HARDOWN : DWG_HDL_SOFTPTR;
5867 deps[i].dep = dwg_add_handleref (dwg, code, pair->value.u, obj);
5868 LOG_TRACE ("%s.%s[%u] = " FORMAT_REF " [H %d]\n", obj->name, "deps", i,
5869 ARGS_REF (deps[i].dep), pair->code);
5870 dxf_free_pair (pair);
5871 }
5872 dwg_dynapi_entity_set_value (o, obj->name, "deps", &deps, 1);
5873
5874 if (class_version > 1)
5875 {
5876 pair = dxf_read_pair (dat);
5877 num = pair ? pair->value.u : 0;
5878 EXPECT_INT_DXF ("num_owned_params", 90, BL);
5879 if (num)
5880 {
5881 hv = (BITCODE_H *)xcalloc (num, sizeof (BITCODE_H));
5882 if (!hv)
5883 return NULL;
5884 }
5885 for (unsigned i = 0; i < num; i++)
5886 {
5887 BITCODE_H hdl;
5888 pair = dxf_read_pair (dat);
5889 if (!pair || pair->type != DWG_VT_HANDLE)
5890 {
5891 LOG_ERROR ("Invalid ASSOCACTION.owned_params[%d] DXF code %d", i,
5892 pair ? pair->code : 0);
5893 return NULL;
5894 }
5895 hdl = dwg_add_handleref (dwg, 3, pair->value.u, obj);
5896 LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n", obj->name,
5897 "owned_params", ARGS_REF (hdl), pair->code);
5898 hv[i] = hdl;
5899 dxf_free_pair (pair);
5900 }
5901 if (num)
5902 dwg_dynapi_entity_set_value (o, obj->name, "owned_params", &hv, 1);
5903
5904 pair = dxf_read_pair (dat);
5905 if (pair == NULL || pair->code != 90)
5906 return pair;
5907 // ignore the ValueParams class_version
5908 dxf_free_pair (pair);
5909
5910 pair = dxf_read_pair (dat);
5911 num = pair ? pair->value.u : 0;
5912 EXPECT_INT_DXF ("num_values", 90, BL);
5913 if (num)
5914 {
5915 values = (Dwg_VALUEPARAM *)xcalloc (num, sizeof (Dwg_VALUEPARAM *));
5916 if (!values)
5917 return NULL;
5918 }
5919 for (unsigned i = 0; i < num; i++)
5920 {
5921 Dwg_VALUEPARAM *value
5922 = (Dwg_VALUEPARAM *)xcalloc (1, sizeof (Dwg_VALUEPARAM));
5923 int success = add_VALUEPARAMs (dwg, dat, value);
5924 values[i] = *value;
5925 if (!success)
5926 return NULL;
5927 }
5928 if (num)
5929 dwg_dynapi_entity_set_value (o, obj->name, "values", &values, 1);
5930 }
5931
5932 return NULL;
5933 }
5934
5935 static Dxf_Pair *
add_RENDERENVIRONMENT(Dwg_Object * restrict obj,Bit_Chain * restrict dat)5936 add_RENDERENVIRONMENT (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
5937 {
5938 Dwg_Object_RENDERENVIRONMENT *o = obj->tio.object->tio.RENDERENVIRONMENT;
5939 Dwg_Data *dwg = obj->parent;
5940 Dxf_Pair *pair;
5941 BITCODE_RC r, g, b;
5942
5943 FIELD_BL (class_version, 90);
5944 FIELD_B (fog_enabled, 290);
5945 FIELD_B (fog_background_enabled, 290);
5946
5947 pair = dxf_read_pair (dat);
5948 EXPECT_DXF (obj->name, fog_color, 280);
5949 r = pair->value.u & 0xff;
5950 dxf_free_pair (pair);
5951
5952 pair = dxf_read_pair (dat);
5953 EXPECT_DXF (obj->name, fog_color, 280);
5954 g = pair->value.u & 0xff;
5955 dxf_free_pair (pair);
5956
5957 pair = dxf_read_pair (dat);
5958 EXPECT_DXF (obj->name, fog_color, 280);
5959 b = pair->value.u & 0xff;
5960 dxf_free_pair (pair);
5961
5962 o->fog_color.method = 0xc3;
5963 o->fog_color.rgb = 0xc3000000 | r << 16 | g << 8 | b;
5964 LOG_TRACE ("%s.fog_color.rgb = 0x%x [3x RC 280]\n", obj->name, o->fog_color.rgb)
5965
5966 FIELD_BD (fog_density_near, 40); /* default 100.0 (opaque fog) */
5967 FIELD_BD (fog_density_far, 40);
5968 FIELD_BD (fog_distance_near, 40); /* default 100.0 (at the far clipping plane) */
5969 FIELD_BD (fog_distance_far, 40);
5970 FIELD_B (environ_image_enabled, 290);
5971 FIELD_T (environ_image_filename, 1);
5972 return NULL;
5973 }
5974 static Dxf_Pair *
add_RENDERSETTINGS(Dwg_Object * restrict obj,Bit_Chain * restrict dat)5975 add_RENDERSETTINGS (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
5976 {
5977 Dwg_Object_RENDERSETTINGS *o = obj->tio.object->tio.RENDERSETTINGS;
5978 Dwg_Data *dwg = obj->parent;
5979 Dxf_Pair *pair;
5980
5981 FIELD_BL (class_version, 90);
5982 FIELD_T (name, 1);
5983 FIELD_B (fog_enabled, 290);
5984 FIELD_B (fog_background_enabled, 290);
5985 FIELD_B (backfaces_enabled, 290);
5986 FIELD_B (environ_image_enabled, 290);
5987 FIELD_T (environ_image_filename, 1);
5988 FIELD_T (description, 1);
5989 FIELD_BL (display_index, 90);
5990 VERSION (R_2013) {
5991 FIELD_B (has_predefined, 290);
5992 }
5993 return NULL;
5994 }
5995
5996 static Dxf_Pair *
add_RENDERGLOBAL(Dwg_Object * restrict obj,Bit_Chain * restrict dat)5997 add_RENDERGLOBAL (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
5998 {
5999 Dwg_Object_RENDERGLOBAL *o = obj->tio.object->tio.RENDERGLOBAL;
6000 Dwg_Data *dwg = obj->parent;
6001 Dxf_Pair *pair;
6002
6003 FIELD_BL (class_version, 90);
6004 FIELD_BL (procedure, 90); /*!< 0 view, 1 crop, 2 selection */
6005 FIELD_BL (destination, 90); /*!< 0 window, 1 viewport */
6006 FIELD_B (save_enabled, 290);
6007 FIELD_T (save_filename, 1);
6008 FIELD_BL (image_width, 90);
6009 FIELD_BL (image_height, 90);
6010 FIELD_B (predef_presets_first, 290);
6011 FIELD_B (highlevel_info, 290);
6012 return NULL;
6013 }
6014
6015 static Dxf_Pair *
add_RENDERENTRY(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6016 add_RENDERENTRY (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6017 {
6018 Dwg_Object_RENDERENTRY *o = obj->tio.object->tio.RENDERENTRY;
6019 Dwg_Data *dwg = obj->parent;
6020 Dxf_Pair *pair;
6021
6022 FIELD_BL (class_version, 90);
6023 FIELD_T (image_file_name, 1);
6024 FIELD_T (preset_name, 1);
6025 FIELD_T (view_name, 1);
6026 FIELD_BL (dimension_x, 90);
6027 FIELD_BL (dimension_y, 90);
6028 FIELD_BS (start_year, 70);
6029 FIELD_BS (start_month, 70);
6030 FIELD_BS (start_day, 70);
6031 FIELD_BS (start_minute, 70);
6032 FIELD_BS (start_second, 70);
6033 FIELD_BS (start_msec, 70);
6034 FIELD_BD (render_time, 40);
6035 FIELD_BL (memory_amount, 90);
6036 FIELD_BL (material_count, 90);
6037 FIELD_BL (light_count, 90);
6038 FIELD_BL (triangle_count, 90);
6039 FIELD_BL (display_index, 90);
6040 return NULL;
6041 }
6042 // more Dynblocks:
6043 static Dxf_Pair *
add_AcDbBlockParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6044 add_AcDbBlockParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6045 {
6046 Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6047 Dwg_Data *dwg = obj->parent;
6048 Dxf_Pair *pair;
6049 // SUBCLASS (AcDbBlockParameter);
6050 FIELD_B (show_properties, 280);
6051 FIELD_B (chain_actions, 281);
6052 return NULL;
6053 }
6054 #if 0
6055 static Dxf_Pair *
6056 add_AcDbBlockGrip (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6057 {
6058 Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6059 Dwg_Data *dwg = obj->parent;
6060 Dxf_Pair *pair;
6061 // SUBCLASS (AcDbBlockGrip)
6062 FIELD_BL (bg_bl91, 91);
6063 FIELD_BL (bg_bl92, 92);
6064 FIELD_3BD (bg_location, 1010);
6065 FIELD_B (bg_insert_cycling, 280);
6066 FIELD_BLd (bg_insert_cycling_weight, 93);
6067 return NULL;
6068 }
6069 #endif
6070 static Dxf_Pair *
add_AcDbBlockGripExpr(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6071 add_AcDbBlockGripExpr (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6072 {
6073 Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6074 Dwg_Data *dwg = obj->parent;
6075 Dxf_Pair *pair;
6076 // SUBCLASS (AcDbBlockGripExpr)
6077 FIELD_BL (grip_type, 91); /* ?? */
6078 FIELD_T (grip_expr, 300)
6079 return NULL;
6080 }
6081 // also for BLOCKLINEARGRIP
6082 static Dxf_Pair *
add_BLOCKALIGNMENTGRIP(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6083 add_BLOCKALIGNMENTGRIP (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6084 {
6085 Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6086 Dwg_Data *dwg = obj->parent;
6087 Dxf_Pair *pair;
6088 FIELD_3BD_1 (orientation, 140);
6089 return NULL;
6090 }
6091 static Dxf_Pair *
add_BLOCKFLIPGRIP(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6092 add_BLOCKFLIPGRIP (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6093 {
6094 Dwg_Object_BLOCKFLIPGRIP *o = obj->tio.object->tio.BLOCKFLIPGRIP;
6095 Dwg_Data *dwg = obj->parent;
6096 Dxf_Pair *pair;
6097 FIELD_3BD_1 (orientation, 140);
6098 FIELD_BL (combined_state, 93);
6099 return NULL;
6100 }
6101
6102 static Dxf_Pair *
add_PERSUBENTMGR(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)6103 add_PERSUBENTMGR (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
6104 Dxf_Pair *restrict pair)
6105 {
6106 Dwg_Object_PERSUBENTMGR *o = obj->tio.object->tio.PERSUBENTMGR;
6107 Dwg_Data *dwg = obj->parent;
6108
6109 EXPECT_INT_DXF ("class_version", 90, BL);
6110 FIELD_BL (unknown_0, 90);
6111 FIELD_BL (unknown_2, 90);
6112 FIELD_BL (numassocsteps, 90);
6113 FIELD_BL (numassocsubents, 90);
6114 FIELD_BL (num_steps, 90);
6115 if (o->num_steps)
6116 {
6117 o->steps = (BITCODE_BL*)xcalloc (o->num_steps, sizeof (BITCODE_BL));
6118 if (!o->steps)
6119 return pair;
6120 for (unsigned i = 0; i < o->num_steps; i++)
6121 {
6122 pair = dxf_read_pair (dat);
6123 if (pair->code != 90)
6124 return pair;
6125 o->steps[i] = pair->value.u;
6126 LOG_TRACE ("%s.steps[%d] = %u [BL %d]\n", obj->name, i,
6127 pair->value.u, pair->code);
6128 dxf_free_pair (pair);
6129 }
6130 }
6131 return NULL;
6132 }
6133
6134 static Dxf_Pair *
add_ASSOCDEPENDENCY(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6135 add_ASSOCDEPENDENCY (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6136 {
6137 Dwg_Object_ASSOCDEPENDENCY *o = obj->tio.object->tio.ASSOCDEPENDENCY;
6138 Dwg_Data *dwg = obj->parent;
6139 Dxf_Pair *pair;
6140
6141 FIELD_BL (class_version, 90);
6142 FIELD_BL (status, 90);
6143 FIELD_B (is_read_dep, 290);
6144 FIELD_B (is_write_dep, 290);
6145 FIELD_B (is_attached_to_object, 290);
6146 FIELD_B (is_delegating_to_owning_action, 290);
6147 FIELD_BLd (order, 90); /* -1 or 0 */
6148 FIELD_HANDLE (dep_on, 3, 330);
6149 FIELD_B (has_name, 290);
6150 if (o->has_name)
6151 {
6152 FIELD_T (name, 1);
6153 }
6154 FIELD_HANDLE (readdep, 4, 330);
6155 FIELD_HANDLE (node, 3, 330);
6156 FIELD_HANDLE (dep_body, 4, 360);
6157 FIELD_BLd (depbodyid, 90);
6158 return NULL;
6159 }
6160
6161 static Dwg_Object *
find_prev_entity(Dwg_Object * obj)6162 find_prev_entity (Dwg_Object *obj)
6163 {
6164 Dwg_Data *dwg = obj->parent;
6165 if (obj->supertype != DWG_SUPERTYPE_ENTITY)
6166 return NULL;
6167 for (BITCODE_BL i = obj->index - 1; i > 0; i--)
6168 {
6169 Dwg_Object *prev = &dwg->object[i];
6170 if (prev->supertype == DWG_SUPERTYPE_ENTITY
6171 && prev->tio.entity->entmode == obj->tio.entity->entmode)
6172 {
6173 if (prev->fixedtype == DWG_TYPE_SEQEND
6174 || prev->fixedtype == DWG_TYPE_ENDBLK)
6175 return NULL;
6176 else
6177 return prev;
6178 }
6179 }
6180 return NULL;
6181 }
6182
6183 /* if it has an absolute ownerhandle */
6184 static int
is_obj_absowner(Dwg_Object * obj)6185 is_obj_absowner (Dwg_Object *obj)
6186 {
6187 if (obj->supertype == DWG_SUPERTYPE_ENTITY)
6188 return 0;
6189 /* With DICTIONARY it may vary */
6190 if (obj->type < DWG_TYPE_GROUP // needs to be absolute 4.1.X
6191 /* obj->fixedtype != DWG_TYPE_DICTIONARY && */
6192 && obj->fixedtype != DWG_TYPE_XRECORD)
6193 return 1;
6194 if (obj->fixedtype == DWG_TYPE_LAYOUT)
6195 return 1;
6196 else // may have relative ref: 8.0.0
6197 return 0;
6198 }
6199
6200 static Dxf_Pair *
new_table_control(const char * restrict name,Bit_Chain * restrict dat,Dwg_Data * restrict dwg)6201 new_table_control (const char *restrict name, Bit_Chain *restrict dat,
6202 Dwg_Data *restrict dwg)
6203 {
6204 // VPORT_CONTROL.num_entries
6205 // VPORT_CONTROL.entries[num_entries] handles
6206 Dwg_Object *obj;
6207 Dxf_Pair *pair = NULL;
6208 Dwg_Object_LTYPE_CONTROL *_obj = NULL; // the largest
6209 int j = 0;
6210 int is_tu = dwg->header.version >= R_2007 ? 1 : 0;
6211 char *fieldname;
6212 char ctrlname[80];
6213 char *dxfname;
6214 BITCODE_B is_xref_ref; // referencable
6215
6216 NEW_OBJECT (dwg, obj);
6217
6218 if (strEQc (name, "BLOCK_RECORD"))
6219 strcpy (ctrlname, "BLOCK_CONTROL");
6220 else if (strEQc (name, "VX_TABLE_RECORD"))
6221 strcpy (ctrlname, "VX_CONTROL");
6222 else
6223 {
6224 strncpy (ctrlname, name, 70);
6225 ctrlname[69] = '\0';
6226 strcat (ctrlname, "_CONTROL");
6227 }
6228 LOG_TRACE ("add %s\n", ctrlname);
6229 dxfname = strdup (ctrlname);
6230
6231 // clang-format off
6232 ADD_TABLE_IF (LTYPE, LTYPE_CONTROL)
6233 else
6234 ADD_TABLE_IF (VPORT, VPORT_CONTROL)
6235 else
6236 ADD_TABLE_IF (APPID, APPID_CONTROL)
6237 else
6238 ADD_TABLE_IF (BLOCK_RECORD, BLOCK_CONTROL)
6239 else
6240 ADD_TABLE_IF (DIMSTYLE, DIMSTYLE_CONTROL)
6241 else
6242 ADD_TABLE_IF (LAYER, LAYER_CONTROL)
6243 else
6244 ADD_TABLE_IF (STYLE, STYLE_CONTROL)
6245 else
6246 ADD_TABLE_IF (UCS, UCS_CONTROL)
6247 else
6248 ADD_TABLE_IF (VIEW, VIEW_CONTROL)
6249 else
6250 ADD_TABLE_IF (VX_TABLE_RECORD, VX_CONTROL)
6251 else
6252 ADD_TABLE_IF (BLOCK_RECORD, BLOCK_CONTROL)
6253 else
6254 // clang-format on
6255 {
6256 // obj->name = "UNKNOWN_OBJ";
6257 obj->fixedtype = DWG_TYPE_UNKNOWN_OBJ;
6258 // undo NEW_OBJECT
6259 free (dxfname);
6260 free (obj->tio.object);
6261 dwg->num_objects--;
6262 LOG_ERROR ("Unknown DXF TABLE %s nor %s_CONTROL", name, name);
6263 return pair;
6264 }
6265 if (!_obj)
6266 {
6267 // obj->name = "UNKNOWN_OBJ";
6268 obj->fixedtype = DWG_TYPE_UNKNOWN_OBJ;
6269 // undo NEW_OBJECT
6270 free (obj->tio.object);
6271 dwg->num_objects--;
6272 LOG_ERROR ("Empty _obj at DXF TABLE %s nor %s_CONTROL", name, name);
6273 return pair;
6274 }
6275 dwg_dynapi_entity_set_value (_obj, obj->name, "objid", &obj->index, 1);
6276 is_xref_ref = 1;
6277 if (dwg_dynapi_entity_field (obj->name, "is_xref_ref"))
6278 dwg_dynapi_entity_set_value (_obj, obj->name, "is_xref_ref", &is_xref_ref,
6279 1);
6280 // default is_xdic_missing
6281 if (dwg->header.version >= R_2004)
6282 obj->tio.object->is_xdic_missing = 1;
6283
6284 pair = dxf_read_pair (dat);
6285 // read common table until next 0 table or endtab
6286 while (pair != NULL && pair->code != 0)
6287 {
6288 switch (pair->code)
6289 {
6290 case 0:
6291 goto do_return;
6292 case 5:
6293 case 105: // for DIMSTYLE
6294 {
6295 Dwg_Object_Ref *ref;
6296 char ctrlobj[80];
6297 dwg_add_handle (&obj->handle, 0, pair->value.u, obj);
6298 ref = dwg_add_handleref (dwg, 3, pair->value.u, obj);
6299 LOG_TRACE ("%s.handle = " FORMAT_H " [H %d]\n", ctrlname,
6300 ARGS_H (obj->handle), pair->code);
6301 // also set the matching HEADER.*_CONTROL_OBJECT
6302 strncpy (ctrlobj, ctrlname, 70);
6303 ctrlobj[69] = '\0';
6304 strcat (ctrlobj, "_OBJECT");
6305 dwg_dynapi_header_set_value (dwg, ctrlobj, &ref, 0);
6306 LOG_TRACE ("HEADER.%s = " FORMAT_REF " [H 0]\n", ctrlobj,
6307 ARGS_REF (ref));
6308 }
6309 break;
6310 case 100: // AcDbSymbolTableRecord, ... ignore
6311 break;
6312 case 102: // TODO {ACAD_XDICTIONARY {ACAD_REACTORS {BLKREFS
6313 break;
6314 case 330: // TODO: most likely {ACAD_REACTORS
6315 {
6316 BITCODE_H owh;
6317 if (is_obj_absowner (obj))
6318 owh = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
6319 else // relative
6320 owh = dwg_add_handleref (dwg, 4, pair->value.u, obj);
6321 obj->tio.object->ownerhandle = owh;
6322 LOG_TRACE ("%s.ownerhandle = " FORMAT_REF " [H 330]\n", ctrlname,
6323 ARGS_REF (owh));
6324 }
6325 break;
6326 case 340:
6327 if (pair->value.u && strEQc (ctrlname, "DIMSTYLE_CONTROL"))
6328 {
6329 Dwg_Object_DIMSTYLE_CONTROL *o
6330 = (Dwg_Object_DIMSTYLE_CONTROL *)_obj;
6331 if (!o->num_morehandles || j < 0 || j >= o->num_morehandles)
6332 {
6333 LOG_ERROR ("Invalid DIMSTYLE_CONTROL.num_morehandles %d or "
6334 "index %d",
6335 o->num_morehandles, j)
6336 break;
6337 }
6338 assert (o->morehandles);
6339 assert (j >= 0);
6340 assert (j < o->num_morehandles);
6341 o->morehandles[j]
6342 = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
6343 LOG_TRACE ("%s.morehandles[%d] = " FORMAT_REF " [H 340]\n",
6344 ctrlname, j, ARGS_REF (o->morehandles[j]));
6345 j++;
6346 }
6347 break;
6348 case 360: // {ACAD_XDICTIONARY TODO
6349 obj->tio.object->xdicobjhandle
6350 = dwg_add_handleref (dwg, 3, pair->value.u, obj);
6351 obj->tio.object->is_xdic_missing = 0;
6352 LOG_TRACE ("%s.xdicobjhandle = " FORMAT_REF " [H 360]\n", ctrlname,
6353 ARGS_REF (obj->tio.object->xdicobjhandle));
6354 break;
6355 case 70:
6356 if (pair->value.u)
6357 {
6358 BITCODE_H *hdls;
6359 // can be -1
6360 BITCODE_BL num_entries = pair->value.i < 0 ? 0 : pair->value.i;
6361 if (num_entries > 32767 // BS overflow
6362 && obj->fixedtype != DWG_TYPE_BLOCK_CONTROL
6363 && obj->fixedtype != DWG_TYPE_LAYER_CONTROL
6364 && obj->fixedtype != DWG_TYPE_VIEW_CONTROL
6365 && obj->fixedtype != DWG_TYPE_STYLE_CONTROL)
6366 {
6367 LOG_ERROR ("%s.num_entries BS overflow", obj->name);
6368 num_entries = 0;
6369 }
6370 hdls = (BITCODE_H *)xcalloc (num_entries, sizeof (BITCODE_H));
6371 if (!hdls)
6372 num_entries = 0;
6373 dwg_dynapi_entity_set_value (_obj, obj->name, "num_entries",
6374 &num_entries, 1);
6375 LOG_TRACE ("%s.num_entries = %u [BL 70]\n", ctrlname,
6376 num_entries);
6377 dwg_dynapi_entity_set_value (_obj, obj->name, "entries", &hdls,
6378 0);
6379 LOG_TRACE ("Add %d %s.%s\n", num_entries, ctrlname, "entries");
6380 }
6381 break;
6382 case 71:
6383 if (strEQc (ctrlname, "DIMSTYLE_CONTROL"))
6384 {
6385 if (pair->value.u)
6386 {
6387 BITCODE_H *hdls;
6388 hdls = (BITCODE_H *)xcalloc (pair->value.u,
6389 sizeof (BITCODE_H));
6390 if (!hdls)
6391 pair->value.u = 0;
6392 dwg_dynapi_entity_set_value (
6393 _obj, obj->name, "num_morehandles", &pair->value, is_tu);
6394 LOG_TRACE ("%s.num_morehandles = %u [BL 71]\n", ctrlname,
6395 pair->value.u);
6396 dwg_dynapi_entity_set_value (_obj, obj->name, "morehandles",
6397 &hdls, 0);
6398 LOG_TRACE ("Add %s.morehandles[%d]\n", ctrlname,
6399 pair->value.u);
6400 }
6401 else
6402 {
6403 LOG_TRACE ("%s.num_morehandles = %u [BL 71]\n", ctrlname,
6404 pair->value.u)
6405 }
6406 break;
6407 }
6408 // fall through
6409 default:
6410 if (pair->code >= 1000 && pair->code < 1999)
6411 {
6412 add_eed (obj, obj->name, pair);
6413 }
6414 else
6415 LOG_ERROR ("Unknown DXF code %d for %s", pair->code, ctrlname);
6416 }
6417 dxf_free_pair (pair);
6418 pair = dxf_read_pair (dat);
6419 }
6420 do_return:
6421 // default NULL handle
6422 if (!obj->tio.object->xdicobjhandle)
6423 {
6424 obj->tio.object->is_xdic_missing = 1;
6425 if (dwg->header.version >= R_13 && dwg->header.version < R_2004)
6426 obj->tio.object->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, obj);
6427 }
6428 return pair;
6429 }
6430
6431 /* by name or by ref.
6432 Note that we don't get the ref->obj here, as it may still move
6433 by realloc dwg->object[].
6434 */
6435 BITCODE_H
find_tablehandle(Dwg_Data * restrict dwg,Dxf_Pair * restrict pair)6436 find_tablehandle (Dwg_Data *restrict dwg, Dxf_Pair *restrict pair)
6437 {
6438 BITCODE_H ref = NULL;
6439 if (pair->code == 8)
6440 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "LAYER");
6441 else if (pair->code == 1) // $DIMBLK
6442 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "BLOCK");
6443 // some name: $DIMSTYLE, $UCSBASE, $UCSORTHOREF, $CMLSTYLE
6444 // not enough info, decide later
6445 else if (pair->code == 2)
6446 ;
6447 else if (pair->code == 3)
6448 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "DIMSTYLE");
6449 // what is/was 4 and 5? VIEW? VX?
6450 else if (pair->code == 6)
6451 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "LTYPE");
6452 else if (pair->code == 7)
6453 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "STYLE");
6454
6455 if (ref) // turn a 2 (hardowner) into a 5 (softref)
6456 return dwg_add_handleref (dwg, 5, ref->absolute_ref, NULL);
6457 /* I think all these >300 are given by hex value, not by name */
6458 if (!ref && pair->code > 300)
6459 {
6460 for (BITCODE_BL i = 0; i < dwg->num_object_refs; i++)
6461 {
6462 Dwg_Object_Ref *refi = dwg->object_ref[i];
6463 if (refi->absolute_ref == (BITCODE_BL)pair->value.u)
6464 {
6465 // no relative offset
6466 ref = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
6467 break;
6468 }
6469 }
6470 if (!ref)
6471 {
6472 // no relative offset
6473 ref = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
6474 }
6475 }
6476 #if 0
6477 else if (pair->code == 331)
6478 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "VPORT");
6479 else if (pair->code == 390)
6480 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "PLOTSTYLENAME");
6481 else if (pair->code == 347)
6482 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "MATERIAL");
6483 else if (pair->code == 345 || pair->code == 346)
6484 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "UCS");
6485 else if (pair->code == 361) // SUN
6486 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "SHADOW");
6487 else if (pair->code == 340) // or TABLESTYLE or LAYOUT or MLINESTYLE ...
6488 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "STYLE");
6489 else if (pair->code == 342 || pair->code == 343)
6490 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "STYLE");
6491 else if (pair->code == 348)
6492 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "VISUALSTYLE");
6493 else if (pair->code == 332)
6494 ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "BACKGROUND");
6495 #endif
6496 return ref;
6497 }
6498
6499 // add pair to XRECORD
6500 static Dxf_Pair *
add_xdata(Bit_Chain * restrict dat,Dwg_Object * restrict obj,Dxf_Pair * restrict pair)6501 add_xdata (Bit_Chain *restrict dat, Dwg_Object *restrict obj,
6502 Dxf_Pair *restrict pair)
6503 {
6504 BITCODE_BL num_xdata, xdata_size;
6505 // add pairs to xdata linked list
6506 Dwg_Resbuf *rbuf;
6507 Dwg_Object_XRECORD *_obj = obj->tio.object->tio.XRECORD;
6508
6509 num_xdata = _obj->num_xdata;
6510 xdata_size = _obj->xdata_size;
6511 rbuf = (Dwg_Resbuf *)calloc (1, sizeof (Dwg_Resbuf));
6512 if (!rbuf)
6513 {
6514 LOG_ERROR ("Out of memory");
6515 return NULL;
6516 }
6517 if (num_xdata && _obj->xdata)
6518 {
6519 Dwg_Resbuf *xdata, *prev;
6520 // add to end, not front
6521 prev = xdata = _obj->xdata;
6522 while (xdata)
6523 {
6524 prev = xdata;
6525 xdata = xdata->nextrb;
6526 }
6527 prev->nextrb = rbuf;
6528 }
6529 else
6530 _obj->xdata = rbuf;
6531
6532 xdata_size += 2; // RS
6533 rbuf->type = pair->code;
6534 switch (dwg_resbuf_value_type (rbuf->type))
6535 {
6536 case DWG_VT_STRING:
6537 if (!pair->value.s)
6538 goto invalid;
6539 PRE (R_2007) // TODO: nice would be the proper target version.
6540 // dat->version
6541 {
6542 Dwg_Data *dwg = obj->parent;
6543 rbuf->value.str.size = strlen (pair->value.s);
6544 rbuf->value.str.codepage = dwg->header.codepage;
6545 rbuf->value.str.is_tu = 0;
6546 rbuf->value.str.u.data = strdup (pair->value.s);
6547 LOG_TRACE ("xdata[%d]: \"%s\" [%d]\n", num_xdata,
6548 rbuf->value.str.u.data, rbuf->type);
6549 xdata_size += 3 + rbuf->value.str.size;
6550 }
6551 LATER_VERSIONS
6552 {
6553 int length = rbuf->value.str.size = strlen (pair->value.s);
6554 if (length > 0)
6555 rbuf->value.str.u.wdata = bit_utf8_to_TU (pair->value.s, 0);
6556 rbuf->value.str.is_tu = 1;
6557 LOG_TRACE ("xdata[%d]: \"%s\" [TU %d]\n", num_xdata,
6558 pair->value.s, rbuf->type);
6559 xdata_size += 2 + 2 * rbuf->value.str.size;
6560 }
6561 break;
6562 case DWG_VT_REAL:
6563 rbuf->value.dbl = pair->value.d;
6564 LOG_TRACE ("xdata[%d]: %f [%d]\n", num_xdata, rbuf->value.dbl,
6565 rbuf->type);
6566 xdata_size += 8;
6567 break;
6568 case DWG_VT_BOOL:
6569 case DWG_VT_INT8:
6570 rbuf->value.i8 = pair->value.i;
6571 LOG_TRACE ("xdata[%d]: %d [%d]\n", num_xdata, (int)rbuf->value.i8,
6572 rbuf->type);
6573 xdata_size += 1;
6574 break;
6575 case DWG_VT_INT16:
6576 rbuf->value.i16 = pair->value.i;
6577 LOG_TRACE ("xdata[%d]: %d [%d]\n", num_xdata, (int)rbuf->value.i16,
6578 rbuf->type);
6579 xdata_size += 2;
6580 break;
6581 case DWG_VT_INT32:
6582 rbuf->value.i32 = pair->value.l;
6583 LOG_TRACE ("xdata[%d]: %ld [%d]\n", num_xdata, (long)rbuf->value.i32,
6584 rbuf->type);
6585 xdata_size += 4;
6586 break;
6587 case DWG_VT_INT64:
6588 rbuf->value.i64 = (BITCODE_BLL)pair->value.rll;
6589 LOG_TRACE ("xdata[%d]: " FORMAT_RLL " [%d]\n", num_xdata,
6590 rbuf->value.i64, rbuf->type);
6591 xdata_size += 8;
6592 break;
6593 case DWG_VT_POINT3D:
6594 rbuf->value.pt[0] = pair->value.d;
6595 dxf_free_pair (pair);
6596 pair = dxf_read_pair (dat);
6597 if (!pair)
6598 return NULL;
6599 rbuf->value.pt[1] = pair->value.d;
6600 dxf_free_pair (pair);
6601 xdata_size += 24;
6602 { // if 30
6603 long pos = bit_position (dat);
6604 pair = dxf_read_pair (dat);
6605 if (!pair)
6606 return NULL;
6607 if (dwg_resbuf_value_type (pair->code) == DWG_VT_POINT3D)
6608 {
6609 rbuf->value.pt[2] = pair->value.d;
6610 LOG_TRACE ("xdata[%d]: (%f,%f,%f) [%d]\n", num_xdata,
6611 rbuf->value.pt[0], rbuf->value.pt[1], rbuf->value.pt[2],
6612 rbuf->type);
6613 }
6614 else
6615 {
6616 bit_set_position (dat, pos); // reset stream
6617 rbuf->value.pt[2] = 0;
6618 LOG_TRACE ("xdata[%d]: (%f,%f) [%d]\n", num_xdata,
6619 rbuf->value.pt[0], rbuf->value.pt[1], rbuf->type);
6620 }
6621 }
6622 break;
6623 case DWG_VT_BINARY:
6624 // convert from hex
6625 if (!pair->value.s)
6626 goto invalid;
6627 {
6628 unsigned len = strlen (pair->value.s);
6629 unsigned blen = len / 2;
6630 unsigned read;
6631 unsigned char *s = (unsigned char *)malloc (blen);
6632 //const char *pos = pair->value.s;
6633 rbuf->value.str.u.data = (char *)s;
6634 rbuf->value.str.size = blen;
6635 if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
6636 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
6637 xdata_size += 1 + len;
6638 LOG_TRACE ("xdata[%d]: ", num_xdata);
6639 // LOG_TRACE_TF (rbuf->value.str.u.data, rbuf->value.str.size);
6640 }
6641 break;
6642 case DWG_VT_HANDLE:
6643 case DWG_VT_OBJECTID:
6644 xdata_size += 8;
6645 dwg_add_handle (&rbuf->value.h, 0, pair->value.u, obj);
6646 LOG_TRACE ("xdata[%d]: " FORMAT_H " [H %d]\n", num_xdata,
6647 ARGS_H (rbuf->value.h), rbuf->type);
6648 break;
6649 case DWG_VT_INVALID:
6650 default:
6651 invalid:
6652 LOG_ERROR ("Invalid group code in rbuf: %d", rbuf->type)
6653 }
6654
6655 num_xdata++;
6656 _obj->num_xdata = num_xdata;
6657 _obj->xdata_size = xdata_size;
6658 return pair;
6659 }
6660
6661 // 350 or 360
6662 static void
add_dictionary_itemhandles(Dwg_Object * restrict obj,Dxf_Pair * restrict pair,char * restrict text)6663 add_dictionary_itemhandles (Dwg_Object *restrict obj, Dxf_Pair *restrict pair,
6664 char *restrict text)
6665 {
6666 // but not DICTIONARYVAR
6667 Dwg_Object_DICTIONARY *_obj
6668 = obj->tio.object->tio.DICTIONARY; // also DICTIONARYWDFLT
6669 Dwg_Data *dwg = obj->parent;
6670 BITCODE_BL num;
6671 BITCODE_H hdl;
6672
6673 if (pair->code == 360)
6674 _obj->is_hardowner = 1;
6675 num = _obj->numitems;
6676 hdl = dwg_add_handleref (dwg, 2, pair->value.u, obj);
6677 LOG_TRACE ("%s.itemhandles[%d] = " FORMAT_REF " [H* %d]\n", obj->name, num,
6678 ARGS_REF (hdl), pair->code);
6679 _obj->itemhandles = (BITCODE_H *)realloc (_obj->itemhandles,
6680 (num + 1) * sizeof (BITCODE_H));
6681 _obj->texts
6682 = (BITCODE_TV *)realloc (_obj->texts, (num + 1) * sizeof (BITCODE_TV));
6683 if (!_obj->itemhandles || !_obj->texts)
6684 {
6685 LOG_ERROR ("Out of memory");
6686 return;
6687 }
6688 _obj->itemhandles[num] = hdl;
6689 _obj->texts[num] = dwg_add_u8_input (dwg, text);
6690 LOG_TRACE ("%s.texts[%d] = %s [T* 3]\n", obj->name, num, text);
6691 _obj->numitems = num + 1;
6692 }
6693
6694 /* read to ent->preview, r2010+ code 160, earlier code 92.
6695 like WIPEOUT, LIGHT, MULTILEADER, ARC_DIMENSION or PROXY GRAPHICS vector
6696 data.
6697 Also handle empty preview_size, such as with MULTILEADER r2000.
6698 */
6699 static Dxf_Pair *
add_ent_preview(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)6700 add_ent_preview (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
6701 Dxf_Pair *restrict pair)
6702 {
6703 Dwg_Object_Entity *ent = obj->tio.entity;
6704 unsigned written = 0;
6705
6706 if (obj->supertype != DWG_SUPERTYPE_ENTITY)
6707 {
6708 LOG_ERROR ("%s is no entity for a preview", obj->name);
6709 return pair;
6710 }
6711 ent->preview_size =
6712 pair->code == 160 ? pair->value.rll :
6713 pair->code == 92 ? pair->value.u : 0;
6714 if (!ent->preview_size && pair->code != 310)
6715 {
6716 dxf_free_pair (pair);
6717 return dxf_read_pair (dat);
6718 }
6719 ent->preview = (BITCODE_TF)calloc (ent->preview_size ? ent->preview_size : 127, 1);
6720 if (!ent->preview)
6721 {
6722 LOG_ERROR ("Out of memory");
6723 return NULL;
6724 }
6725 LOG_TRACE ("%s.preview_size = " FORMAT_BLL " [BLL %d]\n", obj->name,
6726 ent->preview_size, pair->code);
6727
6728 if (pair->code != 310)
6729 {
6730 dxf_free_pair (pair);
6731 pair = dxf_read_pair (dat);
6732 }
6733 while (pair != NULL && pair->code == 310 && pair->value.s)
6734 {
6735 int read;
6736 unsigned len = strlen (pair->value.s);
6737 unsigned blen = len / 2;
6738 //const char *pos = pair->value.s;
6739 BITCODE_TF s;
6740
6741 if (!ent->preview_size)
6742 ent->preview = (BITCODE_TF)realloc (ent->preview, written + blen);
6743 else if (blen + written > ent->preview_size)
6744 {
6745 LOG_ERROR ("%s.preview overflow: %u + written %u > size: " FORMAT_BLL,
6746 obj->name, blen, written, ent->preview_size);
6747 return pair;
6748 }
6749 s = &ent->preview[written];
6750 if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
6751 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
6752 written += read;
6753 LOG_TRACE ("%s.preview += %u (%u/" FORMAT_BLL ")\n", obj->name, blen,
6754 written, ent->preview_size);
6755
6756 dxf_free_pair (pair);
6757 pair = dxf_read_pair (dat);
6758 }
6759 if (!ent->preview_size)
6760 ent->preview_size = written;
6761 if (ent->preview_size)
6762 ent->preview_exists = 1;
6763 return pair;
6764 }
6765
6766 // read to BLOCK_HEADER.preview (310), filling in the size
6767 static Dxf_Pair *
add_block_preview(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)6768 add_block_preview (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
6769 Dxf_Pair *restrict pair)
6770 {
6771 Dwg_Object_BLOCK_HEADER *_obj = obj->tio.object->tio.BLOCK_HEADER;
6772 unsigned written = 0;
6773
6774 if (obj->type != DWG_TYPE_BLOCK_HEADER)
6775 {
6776 LOG_ERROR ("%s is no BLOCK_HEADER for a preview", obj->name);
6777 return pair;
6778 }
6779 if (pair->code != 310)
6780 {
6781 LOG_ERROR ("Invalid %s.preview code %d, need 310", obj->name,
6782 pair->code);
6783 return pair;
6784 }
6785 while (pair != NULL && pair->code == 310)
6786 {
6787 const char *pos = pair->value.s;
6788 const unsigned len = pos ? strlen (pos) : 0;
6789 const unsigned blen = len / 2;
6790 unsigned read;
6791 BITCODE_TF s;
6792
6793 if (len)
6794 {
6795 _obj->preview = (BITCODE_TF)realloc (_obj->preview, written + blen);
6796 s = &_obj->preview[written];
6797 if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
6798 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
6799 written += read;
6800 LOG_TRACE ("BLOCK_HEADER.preview += %u (%u)\n", blen, written);
6801 }
6802 dxf_free_pair (pair);
6803 pair = dxf_read_pair (dat);
6804 }
6805 _obj->preview_size = written;
6806 LOG_TRACE ("BLOCK_HEADER.preview_size = %u [BL 0]\n", written);
6807 return pair;
6808 }
6809
6810 // only need to process conflicting SPLINE DXF codes here. the rest is done via
6811 // dynapi.
6812 // TODO: also for HELIX (where SPLINE is a subclass), pass obj then.
6813 static int
add_SPLINE(Dwg_Entity_SPLINE * restrict o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair,int * restrict jp,BITCODE_RS * restrict flagp)6814 add_SPLINE (Dwg_Entity_SPLINE *restrict o, Bit_Chain *restrict dat,
6815 Dxf_Pair *restrict pair, int *restrict jp,
6816 BITCODE_RS *restrict flagp)
6817 {
6818 int j = *jp;
6819 if (pair->code == 210 || pair->code == 220 || pair->code == 230)
6820 return 0; // ignore extrusion in the dwg (planar only)
6821 else if (pair->code == 70)
6822 {
6823 BITCODE_RS flag = *flagp;
6824 *flagp = flag = pair->value.i;
6825 o->flag = flag;
6826 LOG_TRACE ("SPLINE.flag = %d [70]\n", flag);
6827 if (flag & 1)
6828 {
6829 o->closed_b = 1;
6830 LOG_TRACE ("=> SPLINE.closed_b = 1 [B 0] (bit 0)\n");
6831 }
6832 if (flag & 2)
6833 {
6834 o->periodic = 1;
6835 LOG_TRACE ("=> SPLINE.periodic = 1 [B 0] (bit 1)\n");
6836 }
6837 if (flag & 4)
6838 {
6839 o->rational = 1;
6840 LOG_TRACE ("=> SPLINE.rational = 1 [B 0] (bit 2)\n");
6841 }
6842 if (flag & 16)
6843 {
6844 o->weighted = 1;
6845 LOG_TRACE ("=> SPLINE.weighted = 1 [B 0] (bit 4)\n");
6846 }
6847 if (flag & 32)
6848 o->scenario = 2; // bezier: planar
6849 else
6850 o->scenario = 1;
6851 LOG_TRACE ("=> SPLINE.scenario = %d [BL 0]\n", o->scenario);
6852 return 1; // found
6853 }
6854 else if (pair->code == 71)
6855 {
6856 o->degree = pair->value.i;
6857 LOG_TRACE ("SPLINE.degree = %d [BL 71]\n", o->degree);
6858 return 1; // found
6859 }
6860 else if (pair->code == 72)
6861 {
6862 o->num_knots = pair->value.i;
6863 *jp = 0;
6864 o->knots = (BITCODE_BD *)xcalloc (o->num_knots, sizeof (BITCODE_BD));
6865 if (!o->knots)
6866 {
6867 o->num_knots = 0;
6868 return 0;
6869 }
6870 LOG_TRACE ("SPLINE.num_knots = %d [BS 72]\n", o->num_knots);
6871 return 1; // found
6872 }
6873 else if (pair->code == 73)
6874 {
6875 o->num_ctrl_pts = pair->value.i;
6876 *jp = 0;
6877 o->ctrl_pts = (Dwg_SPLINE_control_point *)xcalloc (
6878 o->num_ctrl_pts, sizeof (Dwg_SPLINE_control_point));
6879 if (!o->ctrl_pts)
6880 {
6881 o->num_ctrl_pts = 0;
6882 return 0;
6883 }
6884 LOG_TRACE ("SPLINE.num_ctrl_pts = %d [BS 73]\n", o->num_ctrl_pts);
6885 return 1; // found
6886 }
6887 else if (pair->code == 74)
6888 {
6889 o->num_fit_pts = pair->value.i;
6890 *jp = 0;
6891 o->fit_pts
6892 = (BITCODE_3BD *)xcalloc (o->num_fit_pts, sizeof (BITCODE_3BD));
6893 if (!o->fit_pts)
6894 {
6895 o->num_fit_pts = 0;
6896 return 0;
6897 }
6898 j = 0;
6899 // o->scenario = 2;
6900 o->flag |= 1024;
6901 LOG_TRACE ("SPLINE.num_fit_pts = %d [BS 74]\n", o->num_fit_pts);
6902 return 1; // found
6903 }
6904 else if (pair->code == 40) // knots[] BD*
6905 {
6906 if (!o->knots || j >= (int)o->num_knots)
6907 {
6908 LOG_ERROR ("SPLINE.knots[%d] overflow, max %d", *jp, o->num_knots);
6909 return 1; // found
6910 }
6911 o->knots[j] = pair->value.d;
6912 LOG_TRACE ("SPLINE.knots[%d] = %f [BD* 40]\n", *jp, pair->value.d);
6913 j++;
6914 *jp = j;
6915 if (j == (int)o->num_knots)
6916 *jp = 0;
6917 return 1; // found
6918 }
6919 else if (pair->code == 10) // ctrl_pts[].x 3BD
6920 {
6921 if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6922 {
6923 LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", *jp,
6924 o->num_ctrl_pts);
6925 return 1; // found
6926 }
6927 o->ctrl_pts[j].parent = o;
6928 o->ctrl_pts[j].x = pair->value.d;
6929 return 1; // found
6930 }
6931 else if (pair->code == 20) // ctrl_pts[].y 3BD
6932 {
6933 if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6934 {
6935 LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", j,
6936 o->num_ctrl_pts);
6937 return 1; // found
6938 }
6939 o->ctrl_pts[j].y = pair->value.d;
6940 return 1; // found
6941 }
6942 else if (pair->code == 30) // ctrl_pts[].z 3BD
6943 {
6944 if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6945 {
6946 LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", j,
6947 o->num_ctrl_pts);
6948 return 1; // found
6949 }
6950 o->ctrl_pts[j].z = pair->value.d;
6951 LOG_TRACE ("SPLINE.ctrl_pts[%d] = (%f, %f, %f) [3BD* 10]\n", *jp,
6952 o->ctrl_pts[j].x, o->ctrl_pts[j].y, o->ctrl_pts[j].z);
6953 j++;
6954 *jp = j;
6955 if (j == (int)o->num_ctrl_pts)
6956 *jp = 0;
6957 return 1; // found
6958 }
6959 else if (pair->code == 41) // ctrl_pts[].z 3BD
6960 {
6961 if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6962 {
6963 LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", j,
6964 o->num_ctrl_pts);
6965 return 1; // found
6966 }
6967 o->ctrl_pts[j].w = pair->value.d;
6968 LOG_TRACE ("SPLINE.ctrl_pts[%d].w = %f [BD* 41]\n", *jp,
6969 o->ctrl_pts[j].w);
6970 j++;
6971 *jp = j;
6972 return 1; // found
6973 }
6974 else if (pair->code == 11) // fit_pts[].x 3BD
6975 {
6976 if (!o->fit_pts || j >= o->num_fit_pts)
6977 {
6978 LOG_ERROR ("SPLINE.fit_pts[%d] overflow, max %d", j, o->num_fit_pts);
6979 return 1; // found
6980 }
6981 o->fit_pts[j].x = pair->value.d;
6982 return 1; // found
6983 }
6984 else if (pair->code == 21) // fit_pts[].y 3BD
6985 {
6986 if (!o->fit_pts || j >= o->num_fit_pts)
6987 {
6988 LOG_ERROR ("SPLINE.fit_pts[%d] overflow, max %d", j, o->num_fit_pts);
6989 return 1; // found
6990 }
6991 o->fit_pts[j].y = pair->value.d;
6992 return 1; // found
6993 }
6994 else if (pair->code == 31) // fit_pts[].z 3BD
6995 {
6996 if (!o->fit_pts || j >= o->num_fit_pts)
6997 {
6998 LOG_ERROR ("SPLINE.fit_pts[%d] overflow, max %d", j, o->num_fit_pts);
6999 return 1; // found
7000 }
7001 o->fit_pts[j].z = pair->value.d;
7002 LOG_TRACE ("SPLINE.fit_pts[%d] = (%f, %f, %f) [3BD* 11]\n", *jp,
7003 o->fit_pts[j].x, o->fit_pts[j].y, o->fit_pts[j].z);
7004 j++;
7005 *jp = j;
7006 if (j == (int)o->num_fit_pts)
7007 *jp = 0;
7008 return 1; // found
7009 }
7010 return 0;
7011 }
7012
7013 static int
add_MLINE(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair,int * restrict jp,int * restrict kp,int * restrict lp)7014 add_MLINE (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
7015 Dxf_Pair *restrict pair, int *restrict jp, int *restrict kp,
7016 int *restrict lp)
7017 {
7018 Dwg_Entity_MLINE *o = obj->tio.entity->tio.MLINE;
7019 int found = 1;
7020 int j = *jp;
7021 int k = *kp;
7022 int l = *lp;
7023
7024 if (pair->code == 72)
7025 {
7026 o->num_verts = pair->value.i;
7027 o->parent = obj->tio.entity;
7028 o->verts = (Dwg_MLINE_vertex *)xcalloc (o->num_verts,
7029 sizeof (Dwg_MLINE_vertex));
7030 if (!o->verts)
7031 {
7032 o->num_verts = 0;
7033 return 0;
7034 }
7035 if (o->num_lines)
7036 {
7037 for (int _j = 0; _j < o->num_verts; _j++)
7038 {
7039 o->verts[_j].lines = (Dwg_MLINE_line *)xcalloc (
7040 o->num_lines, sizeof (Dwg_MLINE_line));
7041 if (!o->verts[_j].lines)
7042 {
7043 o->num_lines = 0;
7044 return 2;
7045 }
7046 }
7047 }
7048 LOG_TRACE ("MLINE.num_verts = %d [BS 72]\n", o->num_verts);
7049 *jp = 0;
7050 }
7051 else if (pair->code == 73)
7052 {
7053 o->num_lines = pair->value.i;
7054 if (o->num_verts && !o->verts[0].lines)
7055 {
7056 for (int _j = 0; _j < o->num_verts; _j++)
7057 {
7058 o->verts[_j].lines = (Dwg_MLINE_line *)xcalloc (
7059 o->num_lines, sizeof (Dwg_MLINE_line));
7060 if (!o->verts[_j].lines)
7061 {
7062 o->num_lines = 0;
7063 return 2;
7064 }
7065 }
7066 }
7067 LOG_TRACE ("MLINE.num_lines = %d [BS 73]\n", o->num_lines);
7068 *kp = 0;
7069 }
7070 else if (pair->code == 11 && o->num_verts)
7071 {
7072
7073 #define CHK_verts \
7074 if (!o->verts || j < 0 || j >= o->num_verts) \
7075 { \
7076 LOG_ERROR ("MLINE.verts[%d] out of bounds", j); \
7077 return 2; \
7078 } \
7079 assert (o->verts); \
7080 assert (j >= 0); \
7081 assert (j < o->num_verts)
7082
7083 CHK_verts;
7084 o->verts[j].parent = o;
7085 o->verts[j].vertex.x = pair->value.d;
7086 }
7087 else if (pair->code == 21 && o->num_verts)
7088 {
7089 CHK_verts;
7090 o->verts[j].vertex.y = pair->value.d;
7091 }
7092 else if (pair->code == 31 && o->num_verts)
7093 {
7094 CHK_verts;
7095 o->verts[j].vertex.z = pair->value.d;
7096 LOG_TRACE ("MLINE.verts[%d] = (%f, %f, %f) [3BD* 11]\n", j,
7097 o->verts[j].vertex.x, o->verts[j].vertex.y,
7098 o->verts[j].vertex.z);
7099 }
7100 else if (pair->code == 12 && o->num_verts)
7101 {
7102 CHK_verts;
7103 o->verts[j].vertex_direction.x = pair->value.d;
7104 }
7105 else if (pair->code == 22 && o->num_verts)
7106 {
7107 CHK_verts;
7108 o->verts[j].vertex_direction.y = pair->value.d;
7109 }
7110 else if (pair->code == 32 && o->num_verts)
7111 {
7112 CHK_verts;
7113 o->verts[j].vertex_direction.z = pair->value.d;
7114 LOG_TRACE ("MLINE.vertex_direction[%d] = (%f, %f, %f) [3BD* 12]\n", j,
7115 o->verts[j].vertex_direction.x,
7116 o->verts[j].vertex_direction.y,
7117 o->verts[j].vertex_direction.z);
7118 }
7119 else if (pair->code == 13 && o->num_verts)
7120 {
7121 CHK_verts;
7122 o->verts[j].miter_direction.x = pair->value.d;
7123 }
7124 else if (pair->code == 23 && o->num_verts)
7125 {
7126 CHK_verts;
7127 o->verts[j].miter_direction.y = pair->value.d;
7128 }
7129 else if (pair->code == 33 && o->num_verts)
7130 {
7131 CHK_verts;
7132 o->verts[j].miter_direction.z = pair->value.d;
7133 LOG_TRACE ("MLINE.miter_direction[%d] = (%f, %f, %f) [3BD* 13]\n", j,
7134 o->verts[j].miter_direction.x, o->verts[j].miter_direction.y,
7135 o->verts[j].miter_direction.z);
7136 // if (j != o->num_verts - 1)
7137 // j++; // not the last
7138 *kp = 0;
7139 }
7140 else if (pair->code == 74 && o->num_lines)
7141 {
7142 CHK_verts;
7143
7144 #define CHK_lines \
7145 if (k < 0 || k >= (int)o->num_lines || !o->verts[j].lines) \
7146 { \
7147 LOG_ERROR ("MLINE.verts[%d].lines[%d] out of bounds", j, k); \
7148 return 2; \
7149 } \
7150 assert (o->verts[j].lines); \
7151 assert (k >= 0 && k < (int)o->num_lines)
7152
7153 CHK_lines;
7154 o->verts[j].lines[k].parent = &o->verts[j];
7155 o->verts[j].lines[k].num_segparms = pair->value.i;
7156 o->verts[j].lines[k].segparms
7157 = (BITCODE_BD *)xcalloc (pair->value.i, sizeof (BITCODE_BD));
7158 if (!o->verts[j].lines[k].segparms)
7159 {
7160 o->verts[j].lines[k].num_segparms = 0;
7161 return 2;
7162 }
7163 LOG_TRACE ("MLINE.v[%d].l[%d].num_segparms = %d [BS 74]\n", j, k,
7164 pair->value.i);
7165 *lp = 0;
7166 }
7167 else if (pair->code == 41 && o->num_lines)
7168 {
7169 CHK_verts;
7170 CHK_lines;
7171 if (l < 0 || l >= o->verts[j].lines[k].num_segparms
7172 || !o->verts[j].lines[k].segparms)
7173 return 2;
7174 assert (l >= 0);
7175 assert (o->verts[j].lines);
7176 assert (l < o->verts[j].lines[k].num_segparms);
7177
7178 o->verts[j].lines[k].segparms[l] = pair->value.d;
7179 LOG_TRACE ("MLINE.v[%d].l[%d].segparms[%d] = %f [BD 41]\n", j, k, l,
7180 pair->value.d);
7181 l++;
7182 *lp = l;
7183 }
7184 else if (pair->code == 75 && o->num_lines)
7185 {
7186 CHK_verts;
7187 CHK_lines;
7188 o->verts[j].lines[k].num_areafillparms = pair->value.i;
7189 LOG_TRACE ("MLINE.v[%d].l[%d].num_areafillparms = %d [BS 75]\n", j, k,
7190 pair->value.i);
7191 if (!pair->value.i)
7192 {
7193 k++; // next line
7194 if (k == o->num_lines)
7195 {
7196 j++; // next vertex
7197 *jp = j;
7198 k = 0;
7199 }
7200 *kp = k;
7201 }
7202 *lp = 0;
7203 }
7204 else if (pair->code == 42 && o->num_lines)
7205 {
7206 CHK_verts;
7207 CHK_lines;
7208 if (l < 0 || l >= o->verts[j].lines[k].num_areafillparms
7209 || !o->verts[j].lines[k].areafillparms)
7210 return 2;
7211 assert (l >= 0);
7212 assert (l < o->verts[j].lines[k].num_areafillparms);
7213
7214 o->verts[j].lines[k].areafillparms[l] = pair->value.d;
7215 LOG_TRACE ("MLINE.v[%d].l[%d].areafillparms[%d] = %f [BD 42]\n", j, k, l,
7216 pair->value.d);
7217 l++;
7218 *lp = l;
7219 if (l == o->verts[j].lines[k].num_areafillparms)
7220 {
7221 l = 0;
7222 *lp = l;
7223 k++; // next line
7224 if (k == o->num_lines)
7225 {
7226 j++; // next vertex
7227 *jp = j;
7228 k = 0;
7229 }
7230 *kp = k;
7231 }
7232 }
7233 else
7234 found = 0;
7235
7236 return found;
7237 }
7238
7239 #undef CHK_verts
7240 #undef CHK_lines
7241
7242 static Dxf_Pair *
add_AcDbEvalExpr(Dwg_Object * restrict obj,char * _obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7243 add_AcDbEvalExpr (Dwg_Object *restrict obj, char *_obj,
7244 Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7245 {
7246 Dwg_EvalExpr *ee;
7247 const char *const evalexpr = "evalexpr";
7248 Dwg_Data *dwg = obj->parent;
7249 const Dwg_DYNAPI_field *f1 = dwg_dynapi_entity_field (obj->name, evalexpr);
7250 if (!f1)
7251 return pair;
7252 ee = (Dwg_EvalExpr *)&(_obj)[f1->offset];
7253 ee->parentid = -1;
7254 while (pair && pair->code != 100)
7255 {
7256 if (pair->code == 90)
7257 {
7258 ee->nodeid = pair->value.u;
7259 LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", obj->name, evalexpr, "nodeid",
7260 pair->value.u, pair->code);
7261 }
7262 else if (pair->code == 98)
7263 {
7264 ee->minor = pair->value.u;
7265 LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", obj->name, evalexpr, "major",
7266 pair->value.u, pair->code);
7267 }
7268 else if (pair->code == 99)
7269 {
7270 ee->minor = pair->value.u;
7271 LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", obj->name, evalexpr, "minor",
7272 pair->value.u, pair->code);
7273 }
7274 else if (pair->code == 70 && !ee->value_code)
7275 {
7276 ee->value_code = pair->value.i;
7277 LOG_TRACE ("%s.%s.%s = %d [BSd %d]\n", obj->name, evalexpr,
7278 "value_code", pair->value.i, pair->code);
7279 }
7280 else if (pair->code == 40 || pair->code == 140)
7281 {
7282 ee->value.num40 = pair->value.d;
7283 LOG_TRACE ("%s.%s.%s = %f [BD %d]\n", obj->name, evalexpr,
7284 "value.num40", pair->value.d, pair->code);
7285 }
7286 else if (pair->code == 10)
7287 {
7288 ee->value.pt2d.x = pair->value.d;
7289 }
7290 else if (pair->code == 20)
7291 {
7292 ee->value.pt2d.y = pair->value.d;
7293 LOG_TRACE ("%s.%s.%s = (%f, %f) [2RD %d]\n", obj->name, evalexpr,
7294 "value.pt2d", ee->value.pt2d.x, pair->value.d,
7295 pair->code);
7296 }
7297 else if (pair->code == 11)
7298 {
7299 ee->value.pt3d.x = pair->value.d;
7300 }
7301 else if (pair->code == 21)
7302 {
7303 ee->value.pt3d.y = pair->value.d;
7304 }
7305 else if (pair->code == 31)
7306 {
7307 ee->value.pt3d.z = pair->value.d;
7308 LOG_TRACE ("%s.%s.%s = (%f, %f, %f) [3RD %d]\n", obj->name, evalexpr,
7309 "value.pt3d", ee->value.pt3d.x, ee->value.pt3d.y,
7310 pair->value.d, pair->code);
7311 }
7312 else if (pair->code == 1)
7313 {
7314 ee->value.text1 = strdup (pair->value.s);
7315 LOG_TRACE ("%s.%s.%s = %s [T %d]\n", obj->name, evalexpr,
7316 "value.text1", pair->value.s, pair->code);
7317 }
7318 else if (pair->code == 70 && ee->value_code)
7319 {
7320 ee->value.short70 = pair->value.i;
7321 LOG_TRACE ("%s.%s.%s = %d [BSd %d]\n", obj->name, evalexpr,
7322 "value.short70", pair->value.i, pair->code);
7323 }
7324 else if (pair->code == 91)
7325 {
7326 ee->value.handle91 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
7327 LOG_TRACE ("%s.%s.%s = " FORMAT_REF " [H %d]\n", obj->name, evalexpr,
7328 "value.handle91", ARGS_REF (ee->value.handle91),
7329 pair->code);
7330 }
7331 else
7332 {
7333 LOG_ERROR ("Invalid DXF code %d for %s", pair->code, "AcDbEvalExpr")
7334 return pair;
7335 }
7336 dxf_free_pair (pair);
7337 pair = dxf_read_pair (dat);
7338 }
7339 return pair;
7340 }
7341
7342 // starts with T 300
7343 // returns NULL on success
7344 static Dxf_Pair *
add_AcDbBlockElement(Dwg_Object * restrict obj,char * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7345 add_AcDbBlockElement (Dwg_Object *restrict obj, char *o,
7346 Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7347 {
7348 Dwg_Data *dwg = obj->parent;
7349 EXPECT_T_DXF ("name", 300);
7350 FIELD_BL (be_major, 98);
7351 FIELD_BL (be_minor, 99);
7352 FIELD_BL (eed1071, 1071);
7353 return NULL;
7354 }
7355
7356 // starts with 100
7357 // returns NULL on success
7358 static Dxf_Pair *
add_AcDbBlockAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7359 add_AcDbBlockAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7360 {
7361 Dwg_Data *dwg = obj->parent;
7362 // all with the same offset
7363 Dwg_Object_BLOCKMOVEACTION *o = obj->tio.object->tio.BLOCKMOVEACTION;
7364 Dxf_Pair *pair;
7365
7366 FIELD_BL (num_actions, 70);
7367 if (o->num_actions)
7368 {
7369 //FIELD_VECTOR (actions, BL, num_actions, 91);
7370 o->actions = (BITCODE_BL*)xcalloc (o->num_actions, sizeof (BITCODE_BL));
7371 if (!o->actions)
7372 return pair;
7373 for (unsigned i = 0; i < o->num_actions; i++)
7374 {
7375 pair = dxf_read_pair (dat);
7376 EXPECT_DXF (obj->name, o->actions[i], 91);
7377 o->actions[i] = pair->value.u;
7378 LOG_TRACE ("%s.actions[%d] = %u [BL 91]\n", obj->name, i,
7379 o->actions[i]);
7380 dxf_free_pair (pair);
7381 }
7382 }
7383 FIELD_BL (num_deps, 71);
7384 //HANDLE_VECTOR (deps, num_deps, 5, 330);
7385 if (o->num_deps)
7386 {
7387 o->deps = (BITCODE_H*)xcalloc (o->num_deps, sizeof (BITCODE_H));
7388 if (!o->deps)
7389 return pair;
7390 for (unsigned i = 0; i < o->num_deps; i++)
7391 {
7392 pair = dxf_read_pair (dat);
7393 EXPECT_DXF (obj->name, o->deps[i], 330);
7394 o->deps[i] = dwg_add_handleref (dwg, 5, pair->value.u, obj);
7395 LOG_TRACE ("%s.deps[%d] = " FORMAT_REF " [H 330]\n", obj->name, i,
7396 ARGS_REF (o->deps[i]));
7397 dxf_free_pair (pair);
7398 }
7399 }
7400 FIELD_3BD (display_location, 1010);
7401 return NULL;
7402 }
7403
7404 // returns NULL on success
7405 static Dxf_Pair *
add_BlockAction_ConnectionPts(Dwg_Object * restrict obj,Bit_Chain * restrict dat,const int first,const int repeat,const int bl_code,const int t_code)7406 add_BlockAction_ConnectionPts (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
7407 const int first, const int repeat,
7408 const int bl_code, const int t_code)
7409 {
7410 Dwg_Data *dwg = obj->parent;
7411 Dwg_Object_BLOCKFLIPACTION *o = obj->tio.object->tio.BLOCKFLIPACTION;
7412 Dxf_Pair *pair;
7413 Dwg_BLOCKACTION_connectionpts conn_pts[6];
7414 const char *const field = "conn_pts";
7415 const Dwg_DYNAPI_field *f = dwg_dynapi_entity_field (obj->name, field);
7416
7417 if (!f)
7418 return (Dxf_Pair *)-1;
7419 if (first)
7420 dwg_dynapi_field_get_value (o, f, &conn_pts);
7421 for (int i = first; i < (first + repeat); i++)
7422 {
7423 pair = dxf_read_pair (dat);
7424 EXPECT_DXF (obj->name, "conn_pts[i].code", bl_code + i - first);
7425 conn_pts[i].code = pair->value.u;
7426 LOG_TRACE ("%s.conn_pts[%d].code = %u [BL %d]\n", obj->name, i,
7427 pair->value.u, bl_code + i - first);
7428 dxf_free_pair (pair);
7429 }
7430
7431 for (int i = first; i < (first + repeat); i++)
7432 {
7433 pair = dxf_read_pair (dat);
7434 EXPECT_DXF (obj->name, "conn_pts[].name", t_code + i - first);
7435 conn_pts[i].name = strdup (pair->value.s);
7436 LOG_TRACE ("%s.conn_pts[%d].name = %s [BL %d]\n", obj->name, i,
7437 pair->value.s, t_code + i - first);
7438 dxf_free_pair (pair);
7439 }
7440 // memcpy'ing back the content
7441 dwg_dynapi_field_set_value (dwg, o, f, &conn_pts, 0);
7442 return NULL;
7443 }
7444
7445 // returns NULL on success
7446 static Dxf_Pair *
add_AcDbBlockActionWithBasePt(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7447 add_AcDbBlockActionWithBasePt (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7448 {
7449 Dwg_Data *dwg = obj->parent;
7450 Dwg_Object_BLOCKROTATEACTION *o = obj->tio.object->tio.BLOCKROTATEACTION;
7451 Dxf_Pair *pair;
7452 pair = add_BlockAction_ConnectionPts (obj, dat, 0, 2, 92, 301);
7453 if (pair)
7454 return pair;
7455 FIELD_3BD (offset, 1011);
7456 FIELD_B (dependent, 280);
7457 FIELD_3BD (base_pt, 1012);
7458 return NULL;
7459 }
7460
7461 // starts with 100
7462 // returns NULL on success
7463 static Dxf_Pair *
add_AcDbBlockFlipAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7464 add_AcDbBlockFlipAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7465 {
7466 Dwg_Data *dwg = obj->parent;
7467 Dxf_Pair *pair;
7468 pair = add_BlockAction_ConnectionPts (obj, dat, 0, 4, 92, 301);
7469 if (pair)
7470 return pair;
7471 return NULL;
7472 }
7473
7474 // starts with 100
7475 // returns NULL on success
7476 static Dxf_Pair *
add_AcDbBlockRotationAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7477 add_AcDbBlockRotationAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7478 {
7479 Dwg_Data *dwg = obj->parent;
7480 Dxf_Pair *pair;
7481 pair = add_BlockAction_ConnectionPts (obj, dat, 2, 1, 94, 303);
7482 if (pair)
7483 return pair;
7484 return NULL;
7485 }
7486
7487 // starts with 100
7488 // returns NULL on success
7489 static Dxf_Pair *
add_AcDbBlockScaleAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7490 add_AcDbBlockScaleAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7491 {
7492 Dwg_Data *dwg = obj->parent;
7493 Dxf_Pair *pair;
7494 pair = add_BlockAction_ConnectionPts (obj, dat, 2, 3, 94, 303);
7495 if (pair)
7496 return pair;
7497 return NULL;
7498 }
7499
7500 // starts with 100
7501 // returns NULL on success
7502 static Dxf_Pair *
add_AcDbBlockMoveAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7503 add_AcDbBlockMoveAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7504 {
7505 Dwg_Data *dwg = obj->parent;
7506 Dwg_Object_BLOCKMOVEACTION *o = obj->tio.object->tio.BLOCKMOVEACTION;
7507 Dxf_Pair *pair;
7508
7509 pair = dxf_read_pair (dat);
7510 EXPECT_DXF (obj->name, conn_pts[0].code, 92);
7511 o->conn_pts[0].code = pair->value.u;
7512 dxf_free_pair (pair);
7513 pair = dxf_read_pair (dat);
7514 EXPECT_DXF (obj->name, conn_pts[0].name, 301);
7515 o->conn_pts[0].name = strdup (pair->value.s);
7516 LOG_TRACE ("%s.conn_pts[0] = (%u, %s)\n", obj->name,
7517 o->conn_pts[0].code, o->conn_pts[0].name);
7518 dxf_free_pair (pair);
7519 pair = dxf_read_pair (dat);
7520 EXPECT_DXF (obj->name, conn_pts[0].code, 93);
7521 o->conn_pts[1].code = pair->value.u;
7522 dxf_free_pair (pair);
7523 pair = dxf_read_pair (dat);
7524 EXPECT_DXF (obj->name, conn_pts[0].name, 302);
7525 o->conn_pts[1].name = strdup (pair->value.s);
7526 LOG_TRACE ("%s.conn_pts[1] = (%u, %s)\n", obj->name,
7527 o->conn_pts[1].code, o->conn_pts[1].name);
7528 dxf_free_pair (pair);
7529
7530 // AcDbBlockAction_doubles
7531 FIELD_BD (action_offset_x, 140);
7532 FIELD_BD (action_offset_y, 141);
7533 FIELD_BD (angle_offset, 0);
7534 /* VALUE_RC (1, 280); Action XY type. 1? */
7535 pair = dxf_read_pair (dat);
7536 dxf_free_pair (pair);
7537 return NULL;
7538 }
7539
7540 // starts with 100
7541 // returns NULL on success
7542 static Dxf_Pair *
add_AcDbBlockStretchAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7543 add_AcDbBlockStretchAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7544 {
7545 Dwg_Data *dwg = obj->parent;
7546 Dwg_Object_BLOCKSTRETCHACTION *o = obj->tio.object->tio.BLOCKSTRETCHACTION;
7547 Dxf_Pair *pair;
7548
7549 pair = dxf_read_pair (dat);
7550 EXPECT_DXF (obj->name, conn_pts[0].code, 92);
7551 o->conn_pts[0].code = pair->value.u;
7552 dxf_free_pair (pair);
7553 pair = dxf_read_pair (dat);
7554 EXPECT_DXF (obj->name, conn_pts[0].name, 301);
7555 o->conn_pts[0].name = strdup (pair->value.s);
7556 LOG_TRACE ("%s.conn_pts[0] = (%u, %s)\n", obj->name,
7557 o->conn_pts[0].code, o->conn_pts[0].name);
7558 dxf_free_pair (pair);
7559 pair = dxf_read_pair (dat);
7560 EXPECT_DXF (obj->name, conn_pts[0].code, 93);
7561 o->conn_pts[1].code = pair->value.u;
7562 dxf_free_pair (pair);
7563 pair = dxf_read_pair (dat);
7564 EXPECT_DXF (obj->name, conn_pts[0].name, 302);
7565 o->conn_pts[1].name = strdup (pair->value.s);
7566 LOG_TRACE ("%s.conn_pts[1] = (%u, %s)\n", obj->name,
7567 o->conn_pts[1].code, o->conn_pts[1].name);
7568 dxf_free_pair (pair);
7569
7570 FIELD_BL (num_pts, 72);
7571 //FIELD_2RD_VECTOR (pts, num_pts, 10);
7572 if (o->num_pts)
7573 {
7574 o->pts = (BITCODE_2RD*)xcalloc (o->num_pts, sizeof (BITCODE_2RD));
7575 if (!o->pts)
7576 return pair;
7577 for (unsigned i = 0; i < o->num_pts; i++)
7578 {
7579 pair = dxf_read_pair (dat);
7580 EXPECT_DXF (obj->name, o->pts[i], 1011);
7581 o->pts[i].x = pair->value.d;
7582 dxf_free_pair (pair);
7583
7584 pair = dxf_read_pair (dat);
7585 EXPECT_DXF (obj->name, o->pts[i], 1021);
7586 o->pts[i].y = pair->value.d;
7587 dxf_free_pair (pair);
7588 LOG_TRACE ("%s.pts[%d] = (%f, %f) [2RD 1011]\n", obj->name, i,
7589 o->pts[i].x, o->pts[i].y);
7590 }
7591 }
7592 FIELD_BL (num_hdls, 73);
7593 // TODO one struct
7594 //HANDLE_VECTOR (hdls, num_hdls, 0, 331);
7595 if (o->num_hdls)
7596 {
7597 o->hdls = (BITCODE_H*)xcalloc (o->num_hdls, sizeof (BITCODE_H));
7598 if (!o->hdls)
7599 return pair;
7600 for (unsigned i = 0; i < o->num_hdls; i++)
7601 {
7602 pair = dxf_read_pair (dat);
7603 EXPECT_DXF (obj->name, o->hdls[i], 331);
7604 o->hdls[i] = dwg_add_handleref (dwg, 5, pair->value.u, obj);
7605 LOG_TRACE ("%s.hdls[%d] = " FORMAT_REF " [H 331]\n", obj->name, i,
7606 ARGS_REF (o->hdls[i]));
7607 dxf_free_pair (pair);
7608 }
7609 //FIELD_VECTOR (shorts, BS, num_hdls, 74);
7610 o->shorts = (BITCODE_BS*)xcalloc (o->num_hdls, sizeof (BITCODE_BS));
7611 if (!o->shorts)
7612 return pair;
7613 for (unsigned i = 0; i < o->num_hdls; i++)
7614 {
7615 pair = dxf_read_pair (dat);
7616 EXPECT_DXF (obj->name, o->shorts[i], 74);
7617 o->shorts[i] = pair->value.i;
7618 LOG_TRACE ("%s.shorts[%d] = %u [BS 74]\n", obj->name, i,
7619 (unsigned)o->shorts[i]);
7620 dxf_free_pair (pair);
7621 }
7622 }
7623
7624 FIELD_BL (num_codes, 75);
7625 // FIXME 3x BL?
7626 //FIELD_VECTOR (codes, BL, num_codes, 76);
7627 if (o->num_codes)
7628 {
7629 o->codes = (BITCODE_BL*)xcalloc (o->num_codes, sizeof (BITCODE_BL));
7630 if (!o->codes)
7631 return pair;
7632 for (unsigned i = 0; i < o->num_pts; i++)
7633 {
7634 pair = dxf_read_pair (dat);
7635 EXPECT_DXF (obj->name, o->codes[i], 76);
7636 o->codes[i] = pair->value.i;
7637 LOG_TRACE ("%s.codes[%d] = %d [BL 76]\n", obj->name, i,
7638 o->codes[i]);
7639 dxf_free_pair (pair);
7640 }
7641 }
7642
7643 // AcDbBlockAction_doubles
7644 FIELD_BD (action_offset_x, 140);
7645 FIELD_BD (action_offset_y, 141);
7646 FIELD_BD (angle_offset, 0);
7647 /* VALUE_RC (1, 280); Action XY type. 1? */
7648 pair = dxf_read_pair (dat);
7649 dxf_free_pair (pair);
7650 return NULL;
7651 }
7652
7653 // starts with BL 91
7654 // returns NULL on success
7655 static Dxf_Pair *
add_AcDbBlockGrip(Dwg_Object * restrict obj,char * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7656 add_AcDbBlockGrip (Dwg_Object *restrict obj, char *o,
7657 Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7658 {
7659 Dwg_Data *dwg = obj->parent;
7660 EXPECT_INT_DXF ("bg_bl91", 91, BL);
7661 FIELD_BL (bg_bl92, 92);
7662 FIELD_3BD (bg_location, 1010);
7663 FIELD_B (bg_insert_cycling, 280);
7664 FIELD_BLd (bg_insert_cycling_weight, 93);
7665 return NULL;
7666 }
7667
7668 // starts with BL 93
7669 // returns NULL on success
7670 static Dxf_Pair *
add_AcDbBlockVisibilityParameter(Dwg_Object * restrict obj,Dwg_Object_BLOCKVISIBILITYPARAMETER * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7671 add_AcDbBlockVisibilityParameter (Dwg_Object *restrict obj,
7672 Dwg_Object_BLOCKVISIBILITYPARAMETER *o,
7673 Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7674 {
7675 Dwg_Data *dwg = obj->parent;
7676 EXPECT_INT_DXF ("num_blocks", 93, BL);
7677 if (o->num_blocks)
7678 {
7679 o->blocks = (BITCODE_H*)xcalloc (o->num_blocks, sizeof (BITCODE_H));
7680 if (!o->blocks)
7681 return pair;
7682 for (unsigned i = 0; i < o->num_blocks; i++)
7683 {
7684 pair = dxf_read_pair (dat);
7685 EXPECT_DXF (obj->name, o->blocks[i], 331);
7686 o->blocks[i] = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
7687 LOG_TRACE ("%s.blocks[%d] = " FORMAT_REF " [H 331]\n", obj->name, i,
7688 ARGS_REF (o->blocks[i]));
7689 dxf_free_pair (pair);
7690 }
7691 }
7692
7693 FIELD_BL (num_states, 92);
7694 if (o->num_states)
7695 {
7696 o->states = (Dwg_BLOCKVISIBILITYPARAMETER_state*)xcalloc (o->num_states,
7697 sizeof (Dwg_BLOCKVISIBILITYPARAMETER_state));
7698 if (!o->states)
7699 return pair;
7700 for (unsigned i = 0; i < o->num_states; i++)
7701 {
7702 pair = dxf_read_pair (dat);
7703 EXPECT_DXF (obj->name, o->states[i].name, 303);
7704 o->states[i].name = strdup (pair->value.s);
7705 LOG_TRACE ("%s.states[%d].name = %s [T 303]\n", obj->name, i, o->states[i].name);
7706 dxf_free_pair (pair);
7707
7708 pair = dxf_read_pair (dat);
7709 EXPECT_DXF (obj->name, o->states[i].num_blocks, 94);
7710 o->states[i].num_blocks = pair->value.u;
7711 LOG_TRACE ("%s.states[%d].num_blocks = %u [BL 94]\n", obj->name, i,
7712 o->states[i].num_blocks);
7713 dxf_free_pair (pair);
7714
7715 if (o->states[i].num_blocks)
7716 {
7717 o->states[i].blocks = (BITCODE_H*)xcalloc (o->states[i].num_blocks,
7718 sizeof (BITCODE_H));
7719 if (!o->states[i].blocks)
7720 return pair;
7721 for (unsigned j = 0; j < o->states[i].num_blocks; j++)
7722 {
7723 pair = dxf_read_pair (dat);
7724 EXPECT_DXF (obj->name, o->states[i].blocks[j], 332);
7725 o->states[i].blocks[j]
7726 = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
7727 LOG_TRACE (
7728 "%s.states[%d].blocks[%d] = " FORMAT_REF " [H 332]\n",
7729 obj->name, i, j, ARGS_REF (o->states[i].blocks[j]));
7730 dxf_free_pair (pair);
7731 }
7732 }
7733
7734 pair = dxf_read_pair (dat);
7735 EXPECT_DXF (obj->name, o->states[i].num_params, 95);
7736 o->states[i].num_params = pair->value.u;
7737 LOG_TRACE ("%s.states[%d].num_params = %u [BL 95]\n", obj->name, i,
7738 o->states[i].num_params);
7739 dxf_free_pair (pair);
7740
7741 if (o->states[i].num_params)
7742 {
7743 o->states[i].params = (BITCODE_H*)xcalloc (o->states[i].num_params,
7744 sizeof (BITCODE_H));
7745 if (!o->states[i].params)
7746 return pair;
7747 for (unsigned j = 0; j < o->states[i].num_params; j++)
7748 {
7749 pair = dxf_read_pair (dat);
7750 EXPECT_DXF (obj->name, o->states[i].params[j], 333);
7751 o->states[i].params[j]
7752 = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
7753 LOG_TRACE (
7754 "%s.states[%d].params[%d] = " FORMAT_REF " [H 333]\n",
7755 obj->name, i, j, ARGS_REF (o->states[i].params[j]));
7756 dxf_free_pair (pair);
7757 }
7758 }
7759 }
7760 }
7761 return NULL;
7762 }
7763
7764 // starts empty
7765 // returns NULL on success
7766 static Dxf_Pair *
add_BlockParam_PropInfo(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dwg_BLOCKPARAMETER_PropInfo * prop,const int i,const int num_code,const int d_code,const int t_code)7767 add_BlockParam_PropInfo (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
7768 Dwg_BLOCKPARAMETER_PropInfo *prop, const int i,
7769 const int num_code, const int d_code, const int t_code)
7770 {
7771 Dwg_Data *dwg = obj->parent;
7772 Dxf_Pair *pair;
7773
7774 pair = dxf_read_pair (dat);
7775 EXPECT_DXF (obj->name, prop->num_connections, num_code);
7776 prop->num_connections = pair->value.u;
7777 LOG_TRACE ("%s.prop%d.num_connections = %u [BL %d]\n", obj->name, i,
7778 pair->value.u, num_code);
7779 dxf_free_pair (pair);
7780 if (prop->num_connections)
7781 {
7782 prop->connections = (Dwg_BLOCKPARAMETER_connection *)xcalloc (
7783 prop->num_connections, sizeof (Dwg_BLOCKPARAMETER_connection));
7784 if (!prop->connections)
7785 return pair;
7786 for (unsigned j = 0; j < prop->num_connections; j++)
7787 {
7788 pair = dxf_read_pair (dat);
7789 EXPECT_DXF (obj->name, prop->connections[j].code, d_code);
7790 prop->connections[j].code = pair->value.u;
7791 LOG_TRACE ("%s.prop[%d].connections[%u].code = %u [BL %d]\n", obj->name, i, j,
7792 pair->value.u, d_code);
7793 dxf_free_pair (pair);
7794
7795 pair = dxf_read_pair (dat);
7796 EXPECT_DXF (obj->name, prop->connections[j].name, t_code);
7797 prop->connections[j].name = strdup (pair->value.s);
7798 LOG_TRACE ("%s.prop[%d].connections[%u].name = %s [T %d]\n", obj->name, i, j,
7799 pair->value.s, t_code);
7800 dxf_free_pair (pair);
7801 }
7802 }
7803 return NULL;
7804 }
7805
7806 // starts empty (on 100 . subclass)
7807 // returns NULL on success
7808 static Dxf_Pair *
add_AcDbBlock1PtParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7809 add_AcDbBlock1PtParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7810 {
7811 Dwg_Object_BLOCKBASEPOINTPARAMETER *o = obj->tio.object->tio.BLOCKBASEPOINTPARAMETER;
7812 Dwg_Data *dwg = obj->parent;
7813 Dxf_Pair * pair;
7814
7815 pair = dxf_read_pair (dat);
7816 EXPECT_DXF (obj->name, "def_pt.x", 1010);
7817 o->def_pt.x = pair->value.d;
7818 dxf_free_pair (pair);
7819 pair = dxf_read_pair (dat);
7820 EXPECT_DXF (obj->name, "def_pt.y", 1020);
7821 o->def_pt.y = pair->value.d;
7822 dxf_free_pair (pair);
7823 pair = dxf_read_pair (dat);
7824 EXPECT_DXF (obj->name, "def_pt.z", 1030);
7825 o->def_pt.z = pair->value.d;
7826 LOG_TRACE ("%s.def_pt = (%f, %f, %f) [3BD 1010]\n", obj->name, o->def_pt.x,
7827 o->def_pt.y, pair->value.d);
7828 dxf_free_pair (pair);
7829
7830 pair = dxf_read_pair (dat);
7831 EXPECT_DXF (obj->name, "num_propinfos", 93); // 2
7832 o->num_propinfos = pair->value.u;
7833 LOG_TRACE ("%s.num_propinfos = %u [BL 93]\n", obj->name, pair->value.u);
7834 dxf_free_pair (pair);
7835
7836 pair = add_BlockParam_PropInfo (obj, dat, &o->prop1, 1, 170, 91, 301);
7837 if (pair)
7838 return pair;
7839 pair = add_BlockParam_PropInfo (obj, dat, &o->prop2, 2, 171, 92, 302);
7840 if (pair)
7841 return pair;
7842
7843 return NULL;
7844 }
7845
7846 // starts empty (on 100 . subclass)
7847 // returns NULL on success
7848 static Dxf_Pair *
add_AcDbBlock2PtParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7849 add_AcDbBlock2PtParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7850 {
7851 Dwg_Object_BLOCKALIGNMENTPARAMETER *o = obj->tio.object->tio.BLOCKALIGNMENTPARAMETER;
7852 Dwg_Data *dwg = obj->parent;
7853 Dxf_Pair * pair;
7854
7855 pair = dxf_read_pair (dat);
7856 EXPECT_DXF (obj->name, "def_basept.x", 1010);
7857 o->def_basept.x = pair->value.d;
7858 dxf_free_pair (pair);
7859 pair = dxf_read_pair (dat);
7860 EXPECT_DXF (obj->name, "def_basept.y", 1020);
7861 o->def_basept.y = pair->value.d;
7862 dxf_free_pair (pair);
7863 pair = dxf_read_pair (dat);
7864 EXPECT_DXF (obj->name, "def_basept.z", 1030);
7865 o->def_basept.z = pair->value.d;
7866 LOG_TRACE ("%s.def_basept = (%f, %f, %f) [3BD 1010]\n", obj->name, o->def_basept.x,
7867 o->def_basept.y, pair->value.d);
7868 dxf_free_pair (pair);
7869
7870 pair = dxf_read_pair (dat);
7871 EXPECT_DXF (obj->name, "def_endpt.x", 1011);
7872 o->def_endpt.x = pair->value.d;
7873 dxf_free_pair (pair);
7874 pair = dxf_read_pair (dat);
7875 EXPECT_DXF (obj->name, "def_endpt.y", 1021);
7876 o->def_endpt.y = pair->value.d;
7877 dxf_free_pair (pair);
7878 pair = dxf_read_pair (dat);
7879 EXPECT_DXF (obj->name, "def_endpt.z", 1031);
7880 o->def_endpt.z = pair->value.d;
7881 LOG_TRACE ("%s.def_endpt = (%f, %f, %f) [3BD 1011]\n", obj->name, o->def_endpt.x,
7882 o->def_endpt.y, pair->value.d);
7883 dxf_free_pair (pair);
7884
7885 pair = dxf_read_pair (dat);
7886 EXPECT_DXF (obj->name, "num_prop_states", 170);
7887 LOG_TRACE ("%s.num_prop_states = %d [BL 170]\n", obj->name, pair->value.u);
7888 dxf_free_pair (pair);
7889 o->prop_states = (BITCODE_BL *)xcalloc (4, sizeof (BITCODE_BL));
7890 if (!o->prop_states)
7891 return dxf_read_pair (dat);
7892 for (unsigned i = 0; i < 4; i++)
7893 {
7894 pair = dxf_read_pair (dat);
7895 EXPECT_DXF (obj->name, prop_states[i], 91);
7896 o->prop_states[i] = pair->value.u;
7897 LOG_TRACE ("%s.prop_states[%d] = %u [BL 91]\n", obj->name, i, pair->value.u);
7898 dxf_free_pair (pair);
7899 }
7900
7901 pair = add_BlockParam_PropInfo (obj, dat, &o->prop1, 1, 171, 92, 301);
7902 if (pair)
7903 return pair;
7904 pair = add_BlockParam_PropInfo (obj, dat, &o->prop2, 2, 172, 93, 302);
7905 if (pair)
7906 return pair;
7907 pair = add_BlockParam_PropInfo (obj, dat, &o->prop3, 3, 173, 94, 303);
7908 if (pair)
7909 return pair;
7910 pair = add_BlockParam_PropInfo (obj, dat, &o->prop4, 4, 174, 95, 304);
7911 if (pair)
7912 return pair;
7913
7914 FIELD_BS (parameter_base_location, 177);
7915 return NULL;
7916 }
7917
7918 typedef int t_codes[4];
7919
7920 // varying dxf codes per object
7921 // returns NULL on success
7922 static Dxf_Pair *
add_AcDbBlockParamValueSet(Dwg_Object * restrict obj,Dwg_BLOCKPARAMVALUESET * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7923 add_AcDbBlockParamValueSet (Dwg_Object *restrict obj, Dwg_BLOCKPARAMVALUESET *o,
7924 Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7925 {
7926 Dwg_Data *dwg = obj->parent;
7927 // i_code, d_code, s_code, t_code
7928 const t_codes codes[] =
7929 {
7930 { 96, 128, 175, 307 }, // 0 AcDbBlock{Linear,Diametric,Radial,Angular}ConstraintParameter{,Entity}
7931 { 96, 141, 175, 307 }, // 1 BLOCKLINEARPARAMETER.value_set
7932 { 96, 141, 175, 307 }, // 2 BLOCKROTATIONPARAMETER.angle_value_set
7933 { 97, 146, 176, 309 }, // 3 BLOCKXYPARAMETER.y_value_set
7934 { 96, 142, 175, 410 }, // 4 BLOCKXYPARAMETER.x_value_set
7935 { 96, 142, 175, 410 }, // 5 BLOCKPOLARPARAMETER.angle_value_set
7936 { 97, 146, 176, 309 }, // 6 BLOCKPOLARPARAMETER.distance_value_set
7937 };
7938 const t_codes *code = &codes[0]; // AcDbBlock{Linear,Diametric,Radial,Angular}ConstraintParameter{,Entity}
7939
7940 // T at first
7941 if (pair->code == 307)
7942 {
7943 if (strEQc (obj->name, "BLOCKLINEARPARAMETER"))
7944 code = &codes[1];
7945 else if (strEQc (obj->name, "BLOCKROTATIONPARAMETER"))
7946 code = &codes[2];
7947 }
7948 else if (pair->code == 309)
7949 {
7950 if (strEQc (obj->name, "BLOCKXYPARAMETER"))
7951 code = &codes[3];
7952 else if (strEQc (obj->name, "BLOCKPOLARPARAMETER"))
7953 code = &codes[6];
7954 }
7955 else if (pair->code == 410)
7956 {
7957 if (strEQc (obj->name, "BLOCKXYPARAMETER"))
7958 code = &codes[4];
7959 else if (strEQc (obj->name, "BLOCKPOLARPARAMETER"))
7960 code = &codes[5];
7961 }
7962 // subclass not object
7963 EXPECT_DXF ("BlockParamValueSet", "desc", (*code)[3]); // t_code
7964 o->desc = strdup (pair->value.s);
7965 LOG_TRACE ("%s.value_set.desc = \"%s\"\n", obj->name, pair->value.s);
7966 dxf_free_pair (pair);
7967
7968 pair = dxf_read_pair (dat);
7969 EXPECT_DXF ("BlockParamValueSet", "flags", (*code)[0]); // i_code
7970 o->flags = pair->value.i;
7971 LOG_TRACE ("%s.value_set.flags = %d\n", obj->name, pair->value.i);
7972 dxf_free_pair (pair);
7973
7974 pair = dxf_read_pair (dat);
7975 EXPECT_DXF ("BlockParamValueSet", "minimum", (*code)[1]); // d_code
7976 o->minimum = pair->value.d;
7977 LOG_TRACE ("%s.value_set.minimum = %f\n", obj->name, pair->value.d);
7978 dxf_free_pair (pair);
7979
7980 pair = dxf_read_pair (dat);
7981 EXPECT_DXF ("BlockParamValueSet", "maximum", (*code)[1]+1);
7982 o->maximum = pair->value.d;
7983 LOG_TRACE ("%s.value_set.maximum = %f\n", obj->name, pair->value.d);
7984 dxf_free_pair (pair);
7985
7986 pair = dxf_read_pair (dat);
7987 EXPECT_DXF ("BlockParamValueSet", "increment", (*code)[1]+2);
7988 o->increment = pair->value.d;
7989 LOG_TRACE ("%s.value_set.increment = %f\n", obj->name, pair->value.d);
7990 dxf_free_pair (pair);
7991
7992 pair = dxf_read_pair (dat);
7993 EXPECT_DXF ("BlockParamValueSet", "num_valuelist", (*code)[2]); // s_code
7994 o->num_valuelist = pair->value.i;
7995 LOG_TRACE ("%s.value_set.num_valuelist = %d\n", obj->name, pair->value.i);
7996 dxf_free_pair (pair);
7997
7998 //FIELD_VECTOR (valuelist, num_valuelist, BD, code[1]+3);
7999 if (!o->num_valuelist)
8000 return NULL;
8001 o->valuelist = (double *)xcalloc (o->num_valuelist, sizeof (double));
8002 if (!o->valuelist)
8003 return dxf_read_pair (dat);
8004
8005 for (unsigned i = 0; i < o->num_valuelist; i++)
8006 {
8007 pair = dxf_read_pair (dat);
8008 EXPECT_DXF ("BLOCKPARAMVALUESET", valuelist[i], (*code)[1]+3);
8009 o->valuelist[i] = pair->value.d;
8010 LOG_TRACE ("%s.value_set.valuelist[%d] = %f [BD %d]\n", obj->name, i,
8011 pair->value.d, pair->code);
8012 dxf_free_pair (pair);
8013 }
8014 return NULL;
8015 }
8016
8017 // starts with 100
8018 // returns NULL on success
8019 static Dxf_Pair *
add_AcDbBlockRotationParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8020 add_AcDbBlockRotationParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8021 {
8022 Dwg_Data *dwg = obj->parent;
8023 Dwg_Object_BLOCKROTATIONPARAMETER *o = obj->tio.object->tio.BLOCKROTATIONPARAMETER;
8024 Dwg_BLOCKPARAMVALUESET *value_set = &o->angle_value_set;
8025 Dxf_Pair *pair;
8026
8027 FIELD_T (angle_name, 305);
8028 FIELD_T (angle_desc, 306);
8029 FIELD_3BD (def_base_angle_pt, 1011);
8030 FIELD_BD (angle, 140);
8031 pair = dxf_read_pair (dat);
8032 EXPECT_DXF (obj->name, angle_value_set, 307);
8033 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
8034 if (pair)
8035 return pair;
8036 return NULL;
8037 }
8038
8039 #define FIELD_CMC(field, dxf) \
8040 dxf_read_CMC (dwg, dat, &o->field, #field, dxf)
8041 #define FIELD_CMC2004(field, dxf) \
8042 SINCE (R_2004) \
8043 FIELD_CMC (field, dxf)
8044
8045 // starts with 71 . 0
8046 // returns NULL on success
8047 static Dxf_Pair *
add_AcDbSectionViewStyle(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8048 add_AcDbSectionViewStyle (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8049 {
8050 Dwg_Data *dwg = obj->parent;
8051 Dwg_Object_SECTIONVIEWSTYLE *o = obj->tio.object->tio.SECTIONVIEWSTYLE;
8052 BITCODE_BD *av;
8053 // starting with 71 . 0 (skipped)
8054 Dxf_Pair *pair;
8055 FIELD_BL (flags, 90);
8056 pair = dxf_read_pair (dat); // skip 71 . 1
8057 FIELD_HANDLE (identifier_style, 5, 340); // textstyle
8058 FIELD_CMC2004 (identifier_color, 62);
8059 FIELD_BD (identifier_height, 40); // 5.0
8060 FIELD_HANDLE (arrow_start_symbol, 5, 340);
8061 FIELD_HANDLE (arrow_end_symbol, 5, 340);
8062 FIELD_CMC2004 (arrow_symbol_color, 62);
8063 FIELD_BD (arrow_symbol_size, 40);
8064 FIELD_T (identifier_exclude_characters, 300); // I, O, Q, S, X, Z
8065 // 40 90 40 90 71
8066 FIELD_BD (arrow_symbol_extension_length, 40);
8067 FIELD_BLd (identifier_position, 90);
8068 FIELD_BD (identifier_offset, 40);
8069 FIELD_BLd (arrow_position, 90);
8070 pair = dxf_read_pair (dat); // skip 71 . 2
8071 FIELD_HANDLE (plane_ltype, 5, 340); // ltype
8072 FIELD_BLd (plane_linewt, 90);
8073 FIELD_CMC2004 (plane_line_color, 62);
8074 FIELD_HANDLE (bend_ltype, 5, 340); // ltype
8075 FIELD_BLd (bend_linewt, 90);
8076 FIELD_CMC2004 (bend_line_color, 62);
8077 FIELD_BD (bend_line_length, 40);
8078 FIELD_BD (end_line_overshoot, 40);
8079 FIELD_BD (end_line_length, 40);
8080 pair = dxf_read_pair (dat); // skip 71 . 3
8081 FIELD_HANDLE (viewlabel_text_style, 5, 340); // textstyle
8082 FIELD_CMC2004 (viewlabel_text_color, 62);
8083 FIELD_BD (viewlabel_text_height, 40);
8084 FIELD_BL (viewlabel_attachment, 90);
8085 FIELD_BD (viewlabel_offset, 40); // 5.0
8086 FIELD_BL (viewlabel_alignment, 90);
8087 FIELD_T (viewlabel_pattern, 300);
8088 pair = dxf_read_pair (dat); // skip 71 . 4
8089 FIELD_CMC2004 (hatch_color, 62);
8090 FIELD_CMC2004 (hatch_bg_color, 62);
8091 FIELD_T (hatch_pattern, 300);
8092 FIELD_BD (hatch_scale, 40);
8093 FIELD_BLd (hatch_transparency, 90);
8094 FIELD_B (unknown_b1, 290);
8095 FIELD_B (unknown_b2, 290);
8096 FIELD_BL (num_hatch_angles, 90);
8097 if (o->num_hatch_angles)
8098 {
8099 o->hatch_angles = (BITCODE_BD *)xcalloc (o->num_hatch_angles, 8);
8100 for (unsigned i = 0; i < o->num_hatch_angles; i++)
8101 {
8102 // FIELD_BD (hatch_angles[i], 40);
8103 pair = dxf_read_pair (dat);
8104 EXPECT_DXF (obj->name, hatch_angles, 40);
8105 o->hatch_angles[i] = pair->value.d;
8106 LOG_TRACE ("%s.%s[%d] = %f [BD %d]\n", obj->name, "hatch_angles", i,
8107 pair->value.d, pair->code);
8108 dxf_free_pair (pair);
8109 }
8110 }
8111 return NULL;
8112 }
8113
8114 static Dxf_Pair *
add_AcDbDetailViewStyle(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8115 add_AcDbDetailViewStyle (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8116 {
8117 Dwg_Data *dwg = obj->parent;
8118 Dwg_Object_DETAILVIEWSTYLE *o = obj->tio.object->tio.DETAILVIEWSTYLE;
8119 // starting with 71 . 0
8120 Dxf_Pair *pair;
8121 FIELD_BL (flags, 90);
8122 pair = dxf_read_pair (dat); // skip 71 . 1
8123 FIELD_HANDLE (identifier_style, 5, 340); // textstyle
8124 FIELD_CMC2004 (identifier_color, 62);
8125 FIELD_BD (identifier_height, 40); // 5.0
8126 FIELD_HANDLE (arrow_symbol, 5, 340);
8127 FIELD_CMC2004 (arrow_symbol_color, 62);
8128 FIELD_BD (arrow_symbol_size, 40);
8129 FIELD_T (identifier_exclude_characters, 300);
8130 FIELD_BD (identifier_offset, 40);
8131 FIELD_RC (identifier_placement, 280);
8132 pair = dxf_read_pair (dat); // skip 71 . 2
8133 FIELD_HANDLE (boundary_ltype, 5, 340); // ltype
8134 FIELD_BLd (boundary_linewt, 90);
8135 FIELD_CMC2004 (boundary_line_color, 62);
8136 pair = dxf_read_pair (dat); // skip 71 . 3
8137 FIELD_HANDLE (viewlabel_text_style, 5, 340); // textstyle
8138 FIELD_CMC2004 (viewlabel_text_color, 62);
8139 FIELD_BD (viewlabel_text_height, 40);
8140 FIELD_BL (viewlabel_attachment, 90);
8141 FIELD_BD (viewlabel_offset, 40); // 5.0
8142 FIELD_BL (viewlabel_alignment, 90);
8143 FIELD_T (viewlabel_pattern, 300);
8144 pair = dxf_read_pair (dat); // skip 71 . 4
8145 FIELD_HANDLE (connection_ltype, 5, 340); // ltype
8146 FIELD_BLd (connection_linewt, 90);
8147 FIELD_CMC2004 (connection_line_color, 62);
8148 FIELD_HANDLE (borderline_ltype, 5, 340);
8149 FIELD_BLd (borderline_linewt, 90);
8150 FIELD_CMC2004 (borderline_color, 62);
8151 FIELD_RC (model_edge, 280); // type, origin, direction
8152 return NULL;
8153 }
8154
8155 static Dxf_Pair *
add_VISUALSTYLE_props(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8156 add_VISUALSTYLE_props (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8157 {
8158 Dwg_Data *dwg = obj->parent;
8159 Dwg_Object_VISUALSTYLE *o = obj->tio.object->tio.VISUALSTYLE;
8160 // starting with 70 . 58 num_props
8161 Dxf_Pair *pair;
8162 FIELD_BS (num_props, 70); // 58
8163 if (o->num_props != 58)
8164 LOG_ERROR ("Invalid VISUALSTYLE.num_props %u != 58", (unsigned)o->num_props);
8165 FIELD_B (b_prop1c, 290); FIELD_BS (b_prop1c_int, 176);
8166 FIELD_B (b_prop1d, 290); FIELD_BS (b_prop1d_int, 176);
8167 FIELD_B (b_prop1e, 290); FIELD_BS (b_prop1e_int, 176);
8168 FIELD_B (b_prop1f, 90); FIELD_BS (b_prop1f_int, 176);
8169 FIELD_B (b_prop20, 290); FIELD_BS (b_prop20_int, 176);
8170 FIELD_B (b_prop21, 90); FIELD_BS (b_prop21_int, 176);
8171 FIELD_B (b_prop22, 290); FIELD_BS (b_prop22_int, 176);
8172 FIELD_B (b_prop23, 290); FIELD_BS (b_prop23_int, 176);
8173 FIELD_B (b_prop24, 290); FIELD_BS (b_prop24_int, 176);
8174 FIELD_BL (bl_prop25, 90); FIELD_BS (bl_prop25_int, 176);
8175 FIELD_BD (bd_prop26, 40); FIELD_BS (bd_prop26_int, 176);
8176 FIELD_BD (bd_prop27, 40); FIELD_BS (bd_prop27_int, 176);
8177 FIELD_BL (bl_prop28, 90); FIELD_BS (bl_prop28_int, 176);
8178 FIELD_CMC (c_prop29, 62); FIELD_BS (c_prop29_int, 176);
8179 FIELD_BL (bl_prop2a, 90); FIELD_BS (bl_prop2a_int, 176);
8180 FIELD_BL (bl_prop2b, 90); FIELD_BS (bl_prop2b_int, 176);
8181 FIELD_CMC (c_prop2c, 62); FIELD_BS (c_prop2c_int, 176);
8182 /*FIELD_B (b_prop2d, 0);*/ FIELD_BS (b_prop2d_int, 176);
8183 FIELD_BL (bl_prop2e, 290); FIELD_BS (bl_prop2e_int, 176);
8184 FIELD_BL (bl_prop2f, 90); FIELD_BS (bl_prop2f_int, 176);
8185 FIELD_BL (bl_prop30, 90); FIELD_BS (bl_prop30_int, 176);
8186 FIELD_B (b_prop31, 290); FIELD_BS (b_prop31_int, 176);
8187 FIELD_BL (bl_prop32, 90); FIELD_BS (bl_prop32_int, 176);
8188 FIELD_CMC (c_prop33, 62); FIELD_BS (c_prop33_int, 176);
8189 FIELD_BD (bd_prop34, 40); FIELD_BS (bd_prop34_int, 176);
8190 FIELD_BL (edge_wiggle, 90); FIELD_BS (edge_wiggle_int, 176); // prop 0x35
8191 FIELD_T (strokes, 1); FIELD_BS (strokes_int, 176); // prop 0x36
8192 FIELD_B (b_prop37, 290); FIELD_BS (b_prop37_int, 176);
8193 FIELD_BD (bd_prop38, 40); FIELD_BS (bd_prop38_int, 176);
8194 FIELD_BD (bd_prop39, 40); FIELD_BS (bd_prop39_int, 176);
8195 return NULL;
8196 }
8197
8198 // return a relative softptr (4 handle) to the prev_ref handle, relative to obj.
8199 static Dwg_Object_Ref *
dwg_link_prev(Dwg_Object_Ref * restrict prev_ref,Dwg_Object * restrict obj)8200 dwg_link_prev (Dwg_Object_Ref *restrict prev_ref, Dwg_Object *restrict obj)
8201 {
8202 Dwg_Object *prev;
8203 Dwg_Data *dwg = obj ? obj->parent : NULL;
8204 if (!prev_ref)
8205 return dwg_add_handleref (dwg, 4, 0, NULL);
8206 if (!obj)
8207 return NULL;
8208 prev = dwg_ref_object (dwg, prev_ref);
8209 if (!prev || prev->supertype != DWG_SUPERTYPE_ENTITY)
8210 return NULL;
8211 if (obj && obj->supertype == DWG_SUPERTYPE_ENTITY)
8212 obj->tio.entity->nolinks = 1;
8213 return dwg_add_handleref (dwg, 4, prev->handle.value, obj);
8214 }
8215
8216 // return a relative softptr (4 handle) to the next_ref handle, relative to obj.
8217 // sets obj nolinks to 1 or 0.
8218 static Dwg_Object_Ref *
dwg_link_next(Dwg_Object_Ref * restrict next_ref,Dwg_Object * restrict obj)8219 dwg_link_next (Dwg_Object_Ref *restrict next_ref, Dwg_Object *restrict obj)
8220 {
8221 Dwg_Object *prev, *next;
8222 Dwg_Object_Ref *prev_ref;
8223 Dwg_Data *dwg = obj ? obj->parent : NULL;
8224 if (!next_ref)
8225 return dwg_add_handleref (dwg, 4, 0, NULL);
8226 if (!obj || obj->supertype != DWG_SUPERTYPE_ENTITY)
8227 return NULL;
8228 next = dwg_ref_object (dwg, next_ref);
8229 if (!next || next->supertype != DWG_SUPERTYPE_ENTITY)
8230 return NULL;
8231 if (next->index == obj->index + 1)
8232 {
8233 prev_ref = obj->tio.entity->prev_entity;
8234 // check if nolinks can be set
8235 if (prev_ref && prev_ref->handleref.code == 8 && prev_ref->handleref.value == 0)
8236 {
8237 obj->tio.entity->nolinks = 1;
8238 LOG_TRACE ("%s.nolinks = 1\n", obj->name);
8239 return NULL;
8240 }
8241 }
8242 obj->tio.entity->nolinks = 0;
8243 return dwg_add_handleref (dwg, 4, next->handle.value, obj);
8244 }
8245
8246 // Also exported to in_json and dwg_api.
8247 // To set to linked list of children in POLYLINE_*/*INSERT
8248 // similar to dwg_fixup_BLOCKS_entities()
8249 void
in_postprocess_SEQEND(Dwg_Object * restrict obj,BITCODE_BL num_owned,BITCODE_H * owned)8250 in_postprocess_SEQEND (Dwg_Object *restrict obj, BITCODE_BL num_owned,
8251 BITCODE_H *owned)
8252 {
8253 Dwg_Data *dwg = obj->parent;
8254 Dwg_Entity_SEQEND *o = obj->tio.entity->tio.SEQEND;
8255 Dwg_Object *owner;
8256 Dwg_Entity_POLYLINE_2D *ow;
8257 const char *owhdls; // the name of the H*
8258 const char *firstfield;
8259 const char *lastfield;
8260
8261 LOG_TRACE ("in_postprocess_SEQEND (%u):\n", (unsigned)num_owned);
8262 if (obj->fixedtype != DWG_TYPE_SEQEND)
8263 return;
8264 owner = dwg_ref_object (dwg, obj->tio.entity->ownerhandle);
8265 if (!owner)
8266 {
8267 if (obj->tio.entity->ownerhandle)
8268 LOG_WARN ("Missing owner from " FORMAT_REF " [H 330]",
8269 ARGS_REF (obj->tio.entity->ownerhandle))
8270 else
8271 LOG_WARN ("Missing owner")
8272 return;
8273 }
8274
8275 obj->tio.entity->ownerhandle->obj = NULL;
8276 owhdls = memBEGINc (owner->name, "POLYLINE_") ? "vertex" : "attribs";
8277 // not the same layout for all possible owners
8278 ow = owner->tio.entity->tio.POLYLINE_2D;
8279 if (!num_owned || !owned)
8280 {
8281 dwg_dynapi_entity_value (ow, owner->name, "num_owned", &num_owned, 0);
8282 dwg_dynapi_entity_value (ow, owner->name, owhdls, &owned, 0);
8283 }
8284 if (!num_owned)
8285 return;
8286
8287 if (memBEGINc (owner->name, "POLYLINE_"))
8288 {
8289 firstfield = "first_vertex";
8290 lastfield = "last_vertex";
8291 }
8292 else
8293 {
8294 firstfield = "first_attrib";
8295 lastfield = "last_attrib";
8296 }
8297 // store all these fields, or just the ones for the requested version?
8298 if ((dwg->header.from_version > R_2000 || dwg->opts & DWG_OPTS_INDXF)
8299 && dwg->header.version <= R_2000
8300 && owned) // if downconvert to r2000
8301 {
8302 Dwg_Object *owned_obj;
8303 Dwg_Object_Entity *ent;
8304 Dwg_Object_Ref *hdl;
8305 // need to turn code 3 into absolute 4.
8306 if (owned[0])
8307 {
8308 hdl = dwg_add_handleref (dwg, 4, owned[0]->handleref.value, NULL);
8309 dwg_dynapi_entity_set_value (ow, owner->name, firstfield, &hdl, 0);
8310 LOG_TRACE ("%s.%s = " FORMAT_REF "[H 0]\n", owner->name, firstfield,
8311 ARGS_REF (hdl));
8312 }
8313 if (owned[num_owned - 1])
8314 {
8315 hdl = dwg_add_handleref (dwg, 4, owned[num_owned - 1]->handleref.value, NULL);
8316 dwg_dynapi_entity_set_value (ow, owner->name, lastfield,
8317 &hdl, 0);
8318 LOG_TRACE ("%s.%s = " FORMAT_REF "[H 0]\n", owner->name, lastfield,
8319 ARGS_REF (hdl));
8320 }
8321 // link the list, because the children have entmode, different to the
8322 // owner.
8323 owned_obj = dwg_ref_object (dwg, owned[0]);
8324 if (!owned_obj || owned_obj->supertype != DWG_SUPERTYPE_ENTITY)
8325 return;
8326 ent = owned_obj->tio.entity;
8327 ent->prev_entity = dwg_link_prev (NULL, owned_obj);
8328 if (ent->prev_entity)
8329 LOG_TRACE ("%s.prev_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8330 ARGS_REF (ent->prev_entity))
8331 else
8332 ent->nolinks = 0;
8333 ent->next_entity = dwg_link_next (num_owned > 1 ? owned[1] : NULL, owned_obj);
8334 if (ent->next_entity)
8335 LOG_TRACE ("%s.next_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8336 ARGS_REF (ent->next_entity))
8337 else
8338 ent->nolinks = 0;
8339
8340 for (unsigned i = 1; i < num_owned; i++)
8341 {
8342 owned_obj = dwg_ref_object (dwg, owned[i]);
8343 if (!owned_obj || owned_obj->supertype != DWG_SUPERTYPE_ENTITY)
8344 continue;
8345 ent = owned_obj->tio.entity;
8346 ent->prev_entity = dwg_link_prev (owned[i - 1], owned_obj);
8347 if (ent->prev_entity)
8348 LOG_TRACE ("%s.prev_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8349 ARGS_REF (ent->prev_entity))
8350 else
8351 ent->nolinks = 0;
8352 ent->next_entity = dwg_link_next (
8353 (i < num_owned - 1) ? owned[i + 1] : NULL, owned_obj);
8354 if (ent->next_entity)
8355 LOG_TRACE ("%s.next_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8356 ARGS_REF (ent->next_entity))
8357 else
8358 ent->nolinks = 0;
8359 }
8360 }
8361 else if ((dwg->header.from_version <= R_2000 || dwg->opts & DWG_OPTS_INDXF)
8362 && dwg->header.version > R_2000
8363 && !owned)
8364 {
8365 BITCODE_H first, last, ref;
8366 unsigned i = 0;
8367 owned = (BITCODE_H *)xcalloc (1, sizeof (BITCODE_H));
8368 dwg_dynapi_entity_value (ow, owner->name, firstfield, &first, 0);
8369 dwg_dynapi_entity_value (ow, owner->name, lastfield, &last, 0);
8370 ref = first;
8371 if (!first || !last || !last->absolute_ref)
8372 {
8373 num_owned = 0;
8374 owned[0] = first;
8375 }
8376 else if (first->absolute_ref == last->absolute_ref)
8377 {
8378 num_owned = 1;
8379 owned[0] = first;
8380 }
8381 else
8382 while (ref && ref->absolute_ref && ref->absolute_ref != last->absolute_ref)
8383 {
8384 Dwg_Object *ref_obj = dwg_ref_object (dwg, ref);
8385 if (!ref_obj || ref_obj->supertype != DWG_SUPERTYPE_ENTITY)
8386 continue;
8387 owned[i] = ref;
8388 if (ref)
8389 LOG_TRACE ("%s.%s[%u] = " FORMAT_REF "[H 0]\n", owner->name,
8390 owhdls, i, ARGS_REF (ref));
8391 ref = ref_obj->tio.entity->next_entity;
8392 i++;
8393 if (i > 1)
8394 {
8395 num_owned = i;
8396 owned = realloc (owned, i * sizeof (BITCODE_H));
8397 }
8398 }
8399 dwg_dynapi_entity_set_value (ow, owner->name, "num_owned", &num_owned, 0);
8400 dwg_dynapi_entity_set_value (ow, owner->name, owhdls, &owned, 0);
8401 }
8402 }
8403
8404 // see GH #138. add vertices / attribs
8405 static void
dxf_postprocess_SEQEND(Dwg_Object * restrict obj)8406 dxf_postprocess_SEQEND (Dwg_Object *restrict obj)
8407 {
8408 Dwg_Data *dwg = obj->parent;
8409 Dwg_Entity_SEQEND *o = obj->tio.entity->tio.SEQEND;
8410 Dwg_Object *owner = dwg_ref_object (dwg, obj->tio.entity->ownerhandle);
8411 Dwg_Entity_POLYLINE_2D *ow;
8412 BITCODE_BL i, j, num_owned = 0;
8413 BITCODE_H seqend;
8414 BITCODE_H *owned = NULL;
8415 const char *owhdls;
8416
8417 LOG_TRACE ("dxf_postprocess_SEQEND:\n");
8418 // r12 and earlier: search for owner backwards
8419 if (dwg->header.from_version < R_13 && !owner && !obj->tio.entity->ownerhandle)
8420 {
8421 for (i = obj->index - 1; i > 0; i--)
8422 {
8423 Dwg_Object *_o = &dwg->object[i];
8424 if (_o->type == DWG_TYPE_INSERT || _o->type == DWG_TYPE_MINSERT
8425 || _o->type == DWG_TYPE_POLYLINE_2D
8426 || _o->type == DWG_TYPE_POLYLINE_3D
8427 || _o->type == DWG_TYPE_POLYLINE_PFACE
8428 || _o->type == DWG_TYPE_POLYLINE_MESH)
8429 {
8430 owner = _o;
8431 obj->tio.entity->ownerhandle
8432 = dwg_add_handleref (dwg, 4, _o->handle.value, obj);
8433 LOG_TRACE ("SEQEND.owner = " FORMAT_H " (%s) [H* 0]\n",
8434 ARGS_H (_o->handle), _o->name);
8435 break;
8436 }
8437 }
8438 }
8439 if (!owner)
8440 {
8441 if (obj->tio.entity->ownerhandle)
8442 LOG_WARN ("Missing owner from " FORMAT_REF " [H 330]",
8443 ARGS_REF (obj->tio.entity->ownerhandle))
8444 else
8445 LOG_WARN ("Missing owner")
8446 return;
8447 }
8448 obj->tio.entity->ownerhandle->obj = NULL;
8449 owhdls = memBEGINc (owner->name, "POLYLINE_") ? "vertex" : "attribs";
8450 ow = owner->tio.entity->tio.POLYLINE_2D;
8451
8452 seqend = dwg_add_handleref (dwg, 3, obj->handle.value, owner);
8453 dwg_dynapi_entity_set_value (ow, owner->name, "seqend", &seqend, 0);
8454 LOG_TRACE ("%s.seqend = " FORMAT_REF " [H 0]\n", owner->name,
8455 ARGS_REF (seqend));
8456 // num_owned is not properly stored in a DXF
8457 // collect children hdls. all objects from owner to here
8458 for (j = 0, i = owner->index + 1; i < obj->index; i++, j++)
8459 {
8460 Dwg_Object *_o = &dwg->object[i];
8461 num_owned = j + 1;
8462 if (dwg->header.from_version >= R_13)
8463 {
8464 owned = (BITCODE_H *)realloc (owned, num_owned * sizeof (BITCODE_H));
8465 owned[j] = dwg_add_handleref (dwg, 3, _o->handle.value, owner);
8466 LOG_TRACE ("%s.%s[%d] = " FORMAT_REF " [H* 0]\n", owner->name,
8467 owhdls, j, ARGS_REF (owned[j]));
8468 }
8469 }
8470 if (!num_owned)
8471 return;
8472 dwg_dynapi_entity_set_value (ow, owner->name, "num_owned", &num_owned, 0);
8473 LOG_TRACE ("%s.num_owned = " FORMAT_BL " [BL 0]\n", owner->name, num_owned);
8474
8475 dwg_dynapi_entity_set_value (ow, owner->name, owhdls, &owned, 0);
8476 in_postprocess_SEQEND (obj, num_owned, owned);
8477 }
8478
8479 static void
dxf_postprocess_LAYOUT(Dwg_Object * restrict obj)8480 dxf_postprocess_LAYOUT (Dwg_Object *restrict obj)
8481 {
8482 Dwg_Data *dwg = obj->parent;
8483 Dwg_Object_LAYOUT *_obj = obj->tio.object->tio.LAYOUT;
8484
8485 if (dwg->header.version < R_2004)
8486 {
8487 _obj->plotsettings.plotview = dwg_find_tablehandle (
8488 dwg, _obj->plotsettings.plotview_name, "PLOTSETTINGS");
8489 /*
8490 if (!_obj->plotsettings.plotview)
8491 _obj->plotsettings.plotview = dwg_add_handleref (dwg, 0, 0, NULL);
8492 */
8493 }
8494 else
8495 _obj->plotsettings.plotview_name
8496 = dwg_handle_name (dwg, "PLOTSETTINGS", _obj->plotsettings.plotview);
8497 }
8498
8499 static void
dxf_postprocess_PLOTSETTINGS(Dwg_Object * restrict obj)8500 dxf_postprocess_PLOTSETTINGS (Dwg_Object *restrict obj)
8501 {
8502 Dwg_Data *dwg = obj->parent;
8503 Dwg_Object_PLOTSETTINGS *_obj = obj->tio.object->tio.PLOTSETTINGS;
8504
8505 if (dwg->header.version < R_2004)
8506 {
8507 _obj->plotview = dwg_find_tablehandle (dwg, _obj->plotview_name, "VIEW");
8508 /*
8509 if (!_obj->plotview)
8510 _obj->plotview = dwg_add_handleref (dwg, 0, 0, NULL);
8511 */
8512 }
8513 else
8514 _obj->plotview_name = dwg_handle_name (dwg, "VIEW", _obj->plotview);
8515 }
8516
8517 // seperate model_space and paper_space into its own fields, out of entries[]
8518 static int
move_out_BLOCK_CONTROL(Dwg_Object * restrict obj,Dwg_Object_BLOCK_CONTROL * restrict _ctrl,const char * f)8519 move_out_BLOCK_CONTROL (Dwg_Object *restrict obj,
8520 Dwg_Object_BLOCK_CONTROL *restrict _ctrl,
8521 const char *f)
8522 {
8523 // move out this entry
8524 for (BITCODE_BL j = 0; j < _ctrl->num_entries; j++)
8525 {
8526 if (_ctrl->entries[j]
8527 && _ctrl->entries[j]->absolute_ref == obj->handle.value)
8528 {
8529 LOG_TRACE ("remove %s from entries[%d]: " FORMAT_H "\n", f, j,
8530 ARGS_H (obj->handle));
8531 _ctrl->num_entries--;
8532 LOG_TRACE ("BLOCK_CONTROL.num_entries = " FORMAT_BL "\n",
8533 _ctrl->num_entries);
8534 if (j < _ctrl->num_entries) // if last, skip move, realloc is enough
8535 /* 1 < 4 (was 5, i.e 0-4): 1, 2, 4-1-1: 2 */
8536 memmove (&_ctrl->entries[j], &_ctrl->entries[j + 1],
8537 (_ctrl->num_entries - j - 1) * sizeof (BITCODE_H));
8538 _ctrl->entries = (BITCODE_H *)realloc (
8539 _ctrl->entries, _ctrl->num_entries * sizeof (BITCODE_H));
8540 return 1;
8541 }
8542 }
8543 return 0;
8544 }
8545
8546 static int
move_out_LTYPE_CONTROL(Dwg_Object * restrict obj,Dwg_Object_LTYPE_CONTROL * restrict _ctrl,const char * f)8547 move_out_LTYPE_CONTROL (Dwg_Object *restrict obj,
8548 Dwg_Object_LTYPE_CONTROL *restrict _ctrl,
8549 const char *f)
8550 {
8551 // move out this entry (byblock, bylayer, continuous)
8552 for (BITCODE_BL j = 0; j < _ctrl->num_entries; j++)
8553 {
8554 if (_ctrl->entries[j]
8555 && _ctrl->entries[j]->absolute_ref == obj->handle.value)
8556 {
8557 LOG_TRACE ("remove %s from entries[%d]: " FORMAT_H "\n", f, j,
8558 ARGS_H (obj->handle));
8559 _ctrl->num_entries--;
8560 LOG_TRACE ("LTYPE_CONTROL.num_entries = " FORMAT_BL "\n",
8561 _ctrl->num_entries);
8562 if (j < _ctrl->num_entries)
8563 memmove (&_ctrl->entries[j], &_ctrl->entries[j + 1],
8564 (_ctrl->num_entries - j - 1) * sizeof (BITCODE_H));
8565 _ctrl->entries = (BITCODE_H *)realloc (
8566 _ctrl->entries, _ctrl->num_entries * sizeof (BITCODE_H));
8567 return 1;
8568 }
8569 }
8570 return 0;
8571 }
8572
8573 static void
postprocess_TEXTlike(Dwg_Object * obj)8574 postprocess_TEXTlike (Dwg_Object *obj)
8575 {
8576 BITCODE_RC dataflags;
8577 BITCODE_2RD alignment_pt;
8578 BITCODE_RD oblique_angle, rotation, width_factor;
8579 BITCODE_BS generation, horiz_alignment, vert_alignment;
8580 BITCODE_H style;
8581 Dwg_Entity_TEXT *_obj = obj->tio.entity->tio.TEXT;
8582
8583 dwg_dynapi_entity_value (_obj, obj->name, "dataflags", &dataflags, NULL);
8584 dwg_dynapi_entity_value (_obj, obj->name, "alignment_pt", &alignment_pt,
8585 NULL);
8586 dwg_dynapi_entity_value (_obj, obj->name, "oblique_angle", &oblique_angle,
8587 NULL);
8588 dwg_dynapi_entity_value (_obj, obj->name, "rotation", &rotation, NULL);
8589 dwg_dynapi_entity_value (_obj, obj->name, "width_factor", &width_factor,
8590 NULL);
8591 dwg_dynapi_entity_value (_obj, obj->name, "generation", &generation, NULL);
8592 dwg_dynapi_entity_value (_obj, obj->name, "horiz_alignment",
8593 &horiz_alignment, NULL);
8594 dwg_dynapi_entity_value (_obj, obj->name, "vert_alignment", &vert_alignment,
8595 NULL);
8596 dwg_dynapi_entity_value (_obj, obj->name, "style", &style, NULL);
8597
8598 if (alignment_pt.x == 0.0 && alignment_pt.y == 0.0)
8599 dataflags |= 2;
8600 if (oblique_angle == 0.0)
8601 dataflags |= 4;
8602 if (rotation == 0.0)
8603 dataflags |= 8;
8604 if (width_factor == 1.0)
8605 dataflags |= 0x10;
8606 if (generation == 0)
8607 dataflags |= 0x20;
8608 if (horiz_alignment == 0)
8609 dataflags |= 0x40;
8610 if (vert_alignment == 0)
8611 dataflags |= 0x80;
8612
8613 if (!style)
8614 {
8615 Dwg_Data *dwg = obj->parent;
8616 // set style to Standard (5.1.11)
8617 style = dwg_find_tablehandle_silent (dwg, "Standard", "STYLE");
8618 if (style)
8619 {
8620 if (style->handleref.code != 5)
8621 style = dwg_add_handleref (dwg, 5, style->absolute_ref, NULL);
8622 dwg_dynapi_entity_set_value (_obj, obj->name, "style", &style, 0);
8623 LOG_TRACE ("%s.style = " FORMAT_REF "\n", obj->name,
8624 ARGS_REF (style));
8625 }
8626 }
8627 dwg_dynapi_entity_set_value (_obj, obj->name, "dataflags", &dataflags, 0);
8628 LOG_TRACE ("%s.dataflags = 0x%x\n", obj->name, dataflags);
8629 }
8630
8631 int
is_textlike(Dwg_Object * restrict obj)8632 is_textlike (Dwg_Object *restrict obj)
8633 {
8634 // has dataflags and common text fields
8635 return obj->fixedtype == DWG_TYPE_TEXT || obj->fixedtype == DWG_TYPE_ATTDEF
8636 || obj->fixedtype == DWG_TYPE_ATTRIB;
8637 }
8638
8639 void
in_postprocess_handles(Dwg_Object * restrict obj)8640 in_postprocess_handles (Dwg_Object *restrict obj)
8641 {
8642 Dwg_Data *dwg = obj->parent;
8643 const char *name = obj->name;
8644 int is_entity = obj->supertype == DWG_SUPERTYPE_ENTITY;
8645
8646 // common_entity_handle_data:
8647 // set is_xdic_missing and xdicobjhandle if <2004
8648 if (is_entity ? !obj->tio.entity->xdicobjhandle
8649 : !obj->tio.object->xdicobjhandle)
8650 {
8651 if (dwg->header.version >= R_2004)
8652 {
8653 if (is_entity)
8654 obj->tio.entity->is_xdic_missing = 1;
8655 else
8656 obj->tio.object->is_xdic_missing = 1;
8657 }
8658 else if (dwg->header.version >= R_13 && !is_entity)
8659 obj->tio.object->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, obj);
8660 else if (dwg->header.version >= R_13 && is_entity)
8661 obj->tio.entity->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, obj);
8662 }
8663
8664 if (is_entity)
8665 {
8666 Dwg_Object_Entity *ent = obj->tio.entity;
8667 if (dwg->header.version >= R_13 && dwg->header.version <= R_14)
8668 {
8669 if (ent->ltype_flags < 3)
8670 ent->isbylayerlt = 1;
8671 }
8672 if (dwg->header.version >= R_13 && dwg->header.version <= R_2000
8673 && obj->type != DWG_TYPE_SEQEND && obj->type != DWG_TYPE_ENDBLK)
8674 {
8675 Dwg_Object *prev = find_prev_entity (obj);
8676 ent->next_entity = NULL; // temp.
8677 if (prev)
8678 {
8679 // if (prev->tio.entity->prev_entity)
8680 // prev->tio.entity->nolinks = 0;
8681 if (prev->index + 1 != obj->index)
8682 {
8683 prev->tio.entity->nolinks = 0;
8684 prev->tio.entity->next_entity
8685 = dwg_add_handleref (dwg, 4, obj->handle.value, prev);
8686 LOG_TRACE ("prev %s(%lX).next_entity = " FORMAT_REF "\n",
8687 prev->name, prev->handle.value,
8688 ARGS_REF (prev->tio.entity->next_entity));
8689 ent->nolinks = 0;
8690 ent->prev_entity
8691 = dwg_add_handleref (dwg, 4, prev->handle.value, obj);
8692 LOG_TRACE ("%s.prev_entity = " FORMAT_REF "\n", name,
8693 ARGS_REF (ent->prev_entity));
8694 }
8695 else
8696 {
8697 LOG_TRACE ("%s.prev_entity = NULL HANDLE 4\n", name);
8698 ent->prev_entity = NULL;
8699 ent->nolinks = 1;
8700 }
8701 }
8702 else if (obj->type == DWG_TYPE_BLOCK)
8703 {
8704 ent->nolinks = 0;
8705 ent->prev_entity = dwg_add_handleref (dwg, 4, 0, NULL);
8706 ent->next_entity = dwg_add_handleref (dwg, 4, 0, NULL);
8707 LOG_TRACE ("%s.prev_entity = next_entity = " FORMAT_REF "\n",
8708 name, ARGS_REF (ent->prev_entity));
8709 }
8710 else
8711 {
8712 LOG_TRACE ("%s.prev_entity = NULL HANDLE 4\n", name);
8713 ent->prev_entity = NULL;
8714 ent->nolinks = 1;
8715 }
8716 }
8717 else if (obj->type != DWG_TYPE_SEQEND && obj->type != DWG_TYPE_ENDBLK)
8718 ent->nolinks = 1;
8719 }
8720 }
8721
8722 #define GET_NUMFIELD(type) \
8723 { \
8724 BITCODE_##type _size; \
8725 memcpy (&_size, &((char *)_obj)[f->offset], f->size); \
8726 LOG_TRACE ("%s = " FORMAT_##type "\n", f->name, _size); \
8727 return (long)_size; \
8728 } \
8729 break;
8730
8731 static long
get_numfield_value(void * restrict _obj,const Dwg_DYNAPI_field * restrict f)8732 get_numfield_value (void *restrict _obj, const Dwg_DYNAPI_field *restrict f)
8733 {
8734 long num = 0;
8735 if (f)
8736 {
8737 switch (f->size)
8738 {
8739 case 1:
8740 GET_NUMFIELD (B)
8741 case 2:
8742 GET_NUMFIELD (BS)
8743 case 4:
8744 GET_NUMFIELD (BL)
8745 case 8:
8746 GET_NUMFIELD (BLL)
8747 default:
8748 LOG_ERROR ("Unknown %s dynapi size %d", f->name, f->size);
8749 }
8750 }
8751 else if (strEQc (f->name, "transmatrix"))
8752 num = 16 * 8; // ignore
8753 else if (strEQc (f->name, "ref"))
8754 {
8755 if (f->size != 4) // fixed size
8756 LOG_WARN ("Need 4 ref array elements, have %ld", num)
8757 else
8758 LOG_TRACE ("Check ref[] 4 ok\n")
8759 }
8760 else
8761 LOG_ERROR ("Unknown num_%s field", f->name);
8762 return 0;
8763 }
8764 #undef GET_NUMFIELD
8765
8766 /* For tables, entities and objects.
8767 */
8768 static Dxf_Pair *
new_object(char * restrict name,char * restrict dxfname,Bit_Chain * restrict dat,Dwg_Data * restrict dwg,BITCODE_BL ctrl_id,BITCODE_BL * i_p)8769 new_object (char *restrict name, char *restrict dxfname,
8770 Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
8771 BITCODE_BL ctrl_id, BITCODE_BL *i_p)
8772 {
8773 const int is_tu = 1;
8774 Dwg_Object *obj;
8775 Dxf_Pair *pair = dxf_read_pair (dat);
8776 Dwg_Object_APPID *_obj = NULL; // the smallest
8777 // we'd really need a Dwg_Object_TABLE or Dwg_Object_Generic type
8778 char ctrlname[80];
8779 char subclass[80];
8780 char text[256]; // FIXME
8781 int in_xdict = 0;
8782 int in_reactors = 0;
8783 int in_blkrefs = 0;
8784 int in_embedobj = 0;
8785 int is_entity = is_dwg_entity (name) || strEQc (name, "DIMENSION");
8786 // BITCODE_BL rcount1, rcount2, rcount3, vcount;
8787 // Bit_Chain *hdl_dat, *str_dat;
8788 int j = 0, k = 0, l = 0, error = 0;
8789 BITCODE_BL i = i_p ? *i_p : 0;
8790 int cur_cell = -1;
8791 unsigned written = 0;
8792 BITCODE_RL curr_inserts = 0;
8793 BITCODE_RS flag = 0;
8794 BITCODE_BB scale_flag;
8795 BITCODE_3BD pt;
8796 Dwg_Object *ctrl;
8797 const Dwg_DYNAPI_field *prev_vstyle = NULL;
8798 subclass[0] = '\0';
8799
8800 if (ctrl_id || i)
8801 {
8802 LOG_TRACE ("add %s [%d]\n", name, i)
8803 }
8804 else
8805 {
8806 if (strcmp (name, dxfname) != 0)
8807 LOG_TRACE ("add %s (%s)\n", name, dxfname)
8808 else
8809 LOG_TRACE ("add %s\n", name)
8810 }
8811
8812 if (is_entity)
8813 {
8814 NEW_ENTITY (dwg, obj);
8815
8816 obj->tio.entity->is_xdic_missing = 1;
8817 obj->tio.entity->color.index = 256; // ByLayer
8818 obj->tio.entity->ltype_scale = 1.0;
8819 if (strEQc (name, "SEQEND") || memBEGINc (name, "VERTEX"))
8820 obj->tio.entity->linewt = 0x1c;
8821 else
8822 obj->tio.entity->linewt = 0x1d;
8823
8824 if (*name == '3')
8825 {
8826 // Looks dangerous but name[80] is big enough
8827 memmove (&name[1], &name[0], strlen (name) + 1);
8828 *name = '_';
8829 }
8830 if (strEQc (name, "DIMENSION"))
8831 { // the biggest
8832 ADD_ENTITY (DIMENSION_ANG2LN);
8833 }
8834 // broken (causes acad to hang on audit redraw)
8835 /*
8836 else if (is_class_unstable (name)
8837 && strEQc (name, "WIPEOUT"))
8838 {
8839 LOG_ERROR ("Unhandled DXF entity %s", name);
8840 name = (char*)"UNKNOWN_ENT";
8841 ADD_ENTITY (UNKNOWN_ENT);
8842 return pair;
8843 }
8844 */
8845 else
8846 {
8847 // clang-format off
8848 // ADD_ENTITY by name
8849 // check all objects
8850 #undef DWG_ENTITY
8851 #define DWG_ENTITY(token) \
8852 if (strEQc (name, #token)) \
8853 { \
8854 ADD_ENTITY (token); \
8855 goto found_ent; \
8856 } \
8857 else
8858
8859 #include "objects.inc"
8860 //final else
8861 LOG_WARN ("Unknown object %s", name);
8862
8863 #undef DWG_ENTITY
8864 #define DWG_ENTITY(token)
8865 // clang-format on
8866 found_ent:;
8867 }
8868 }
8869 else
8870 {
8871 NEW_OBJECT (dwg, obj);
8872
8873 obj->tio.object->is_xdic_missing = 1;
8874 if (!ctrl_id) // no table
8875 {
8876 // clang-format off
8877 // ADD_OBJECT by name
8878 // check all objects
8879 #undef DWG_OBJECT
8880 #define DWG_OBJECT(token) \
8881 if (strEQc (name, #token)) \
8882 { \
8883 ADD_OBJECT (token); \
8884 goto found_obj; \
8885 }
8886
8887 #include "objects.inc"
8888
8889 #undef DWG_OBJECT
8890 #define DWG_OBJECT(token)
8891
8892 found_obj:
8893 ;
8894 // clang-format on
8895 }
8896 else // a table
8897 {
8898 if (strEQc (name, "BLOCK_RECORD"))
8899 {
8900 // strcpy (name, "BLOCK_HEADER");
8901 strcpy (ctrlname, "BLOCK_CONTROL");
8902 }
8903 else
8904 {
8905 strncpy (ctrlname, name, 70);
8906 ctrlname[69] = '\0';
8907 strcat (ctrlname, "_CONTROL");
8908 }
8909
8910 // clang-format off
8911 ADD_TABLE_IF (LTYPE, LTYPE)
8912 else
8913 ADD_TABLE_IF (VPORT, VPORT)
8914 else
8915 ADD_TABLE_IF (APPID, APPID)
8916 else
8917 ADD_TABLE_IF (DIMSTYLE, DIMSTYLE)
8918 else
8919 ADD_TABLE_IF (LAYER, LAYER)
8920 else
8921 ADD_TABLE_IF (STYLE, STYLE)
8922 else
8923 ADD_TABLE_IF (UCS, UCS)
8924 else
8925 ADD_TABLE_IF (VIEW, VIEW)
8926 else
8927 ADD_TABLE_IF (BLOCK_RECORD, BLOCK_HEADER)
8928 else
8929 ADD_TABLE_IF (VX_TABLE_RECORD, VX_TABLE_RECORD)
8930 else
8931 // clang-format on
8932 {
8933 dwg->num_objects--;
8934 LOG_ERROR ("Unknown DXF AcDbSymbolTableRecord %s, skipping", name);
8935 return pair;
8936 }
8937 }
8938 }
8939
8940 if (!_obj)
8941 {
8942 dwg->num_objects--;
8943 LOG_ERROR ("Empty _obj at DXF AcDbSymbolTableRecord %s, skipping", name);
8944 return pair;
8945 }
8946 ctrl = &dwg->object[ctrl_id];
8947
8948 {
8949 const Dwg_DYNAPI_field *f1;
8950 BITCODE_B is_xref_ref = 1;
8951 // set defaults not in dxf:
8952 if (dwg_dynapi_entity_field (obj->name, "is_xref_ref"))
8953 dwg_dynapi_entity_set_value (_obj, obj->name, "is_xref_ref",
8954 &is_xref_ref, 0);
8955 if ((f1 = dwg_dynapi_entity_field (obj->name, "scale_flag"))
8956 && (memBEGINc(f1->type, "BB")))
8957 {
8958 scale_flag = 3;
8959 dwg_dynapi_entity_set_value (_obj, obj->name, "scale_flag",
8960 &scale_flag, 0);
8961 LOG_TRACE ("%s.scale_flag = 3 (default)\n", obj->name);
8962 }
8963 if ((f1 = dwg_dynapi_entity_field (obj->name, "width_factor"))
8964 && (memBEGINc(f1->type, "RD") || memBEGINc(f1->type, "BD")))
8965 {
8966 BITCODE_BD width_factor = 1.0;
8967 dwg_dynapi_entity_set_value (_obj, obj->name, "width_factor",
8968 &width_factor, 0);
8969 LOG_TRACE ("%s.width_factor = 1.0 (default)\n", obj->name);
8970 }
8971 if ((f1 = dwg_dynapi_entity_field (obj->name, "scale"))
8972 && (memBEGINc(f1->type, "3BD")))
8973 {
8974 pt.x = pt.y = pt.z = 1.0;
8975 dwg_dynapi_entity_set_value (_obj, obj->name, "scale", &pt, 0);
8976 LOG_TRACE ("%s.scale = (1,1,1) (default)\n", obj->name);
8977 pt.x = pt.y = pt.z = 0.0;
8978 }
8979 if ((f1 = dwg_dynapi_entity_field (obj->name, "extrusion"))
8980 && (memBEGINc(f1->type, "BE") || memBEGINc(f1->type, "3BD")))
8981 {
8982 pt.x = pt.y = 0.0;
8983 pt.z = 1.0;
8984 dwg_dynapi_entity_set_value (_obj, obj->name, "extrusion", &pt, 0);
8985 LOG_TRACE ("%s.extrusion = (0,0,1) (default)\n", obj->name);
8986 pt.z = 0.0;
8987 }
8988 }
8989 // more DXF defaults
8990 if (obj->fixedtype == DWG_TYPE_LAYOUT)
8991 {
8992 Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
8993 o->plotsettings.paper_units = 1.0; // default
8994 }
8995 else if (obj->fixedtype == DWG_TYPE_PLOTSETTINGS)
8996 {
8997 Dwg_Object_PLOTSETTINGS *o = obj->tio.object->tio.PLOTSETTINGS;
8998 o->paper_units = 1.0; // default
8999 }
9000 else if (obj->fixedtype == DWG_TYPE_DIMSTYLE)
9001 {
9002 Dwg_Object_DIMSTYLE *o = obj->tio.object->tio.DIMSTYLE;
9003 o->DIMSCALE = o->DIMLFAC = o->DIMTFAC = 1.0; // default
9004 o->DIMALTU = o->DIMLUNIT = 2; // default
9005 o->DIMFIT = 3;
9006 o->DIMLWD = o->DIMLWE = -2;
9007 }
9008 else if (obj->fixedtype == DWG_TYPE_TABLESTYLE)
9009 {
9010 Dwg_Object_TABLESTYLE *o = obj->tio.object->tio.TABLESTYLE;
9011 o->num_rowstyles = 3;
9012 o->rowstyles = (Dwg_TABLESTYLE_rowstyles *)xcalloc (
9013 3, sizeof (Dwg_TABLESTYLE_rowstyles));
9014 if (!o->rowstyles)
9015 {
9016 o->num_rowstyles = 0;
9017 goto invalid_dxf;
9018 }
9019 for (j = 0; j < 3; j++)
9020 {
9021 o->rowstyles[j].borders = (Dwg_TABLESTYLE_border *)xcalloc (
9022 6, sizeof (Dwg_TABLESTYLE_border));
9023 o->rowstyles[j].num_borders = 6;
9024 for (k = 0; k < 3; k++) // defaults: ByLayer
9025 {
9026 o->rowstyles[j].borders[k].visible = 1;
9027 o->rowstyles[j].borders[k].linewt = 29;
9028 o->rowstyles[j].borders[k].color.index = 256;
9029 }
9030 }
9031 k = 0;
9032 j = 0;
9033 }
9034 /*
9035 else if (is_textlike (obj))
9036 {
9037 BITCODE_RC dataflags = 0x2 + 0x4 + 0x8;
9038 dwg_dynapi_entity_set_value (_obj, obj->name, "dataflags",
9039 &dataflags, 0);
9040 }
9041 */
9042 else if (obj->fixedtype == DWG_TYPE_MTEXT)
9043 {
9044 BITCODE_H style;
9045 Dwg_Entity_MTEXT *o = obj->tio.entity->tio.MTEXT;
9046 o->x_axis_dir.x = 1.0;
9047 // set style to Standard (5.1.11)
9048 style = dwg_find_tablehandle_silent (dwg, "Standard", "STYLE");
9049 if (style)
9050 {
9051 if (style->handleref.code != 5)
9052 style = dwg_add_handleref (dwg, 5, style->absolute_ref, NULL);
9053 o->style = style;
9054 }
9055 }
9056 // Some objects have various subtypes under one name, like DIMENSION.
9057 // TODO OBJECTCONTEXTDATA, ...
9058
9059 // read table fields until next 0 table or 0 ENDTAB
9060 while (pair != NULL && pair->code != 0)
9061 {
9062 start_loop:
9063 if (pair == NULL)
9064 {
9065 pair = dxf_read_pair (dat);
9066 DXF_RETURN_EOF (pair);
9067 }
9068 #if 0
9069 // don't set defaults. TODO but needed to reset counters j, k, l
9070 if ((pair->type == DWG_VT_INT8 || pair->type == DWG_VT_INT16 || pair->type == DWG_VT_BOOL) &&
9071 pair->value.i == 0)
9072 goto next_pair;
9073 else if (pair->type == DWG_VT_REAL && pair->value.d == 0.0)
9074 goto next_pair;
9075 else if ((pair->type == DWG_VT_INT32 || pair->type == DWG_VT_INT64) &&
9076 pair->value.l == 0L)
9077 goto next_pair;
9078 #endif
9079 // start_switch:
9080 switch (pair->code)
9081 { // common flags: name, xref
9082 case 0:
9083 if (strEQc (name, "SEQEND"))
9084 dxf_postprocess_SEQEND (obj);
9085 return pair;
9086 case 105: /* DIMSTYLE only for 5 */
9087 if (strNE (name, "DIMSTYLE"))
9088 goto object_default;
9089 // fall through
9090 case 5:
9091 {
9092 obj->handle.value = pair->value.u;
9093 // check for existing BLOCK_HEADER.*Model_Space
9094 if (obj->fixedtype == DWG_TYPE_BLOCK_HEADER
9095 && dwg->object[0].handle.value == pair->value.u
9096 && obj->tio.object->tio.BLOCK_HEADER
9097 != dwg->object[0].tio.object->tio.BLOCK_HEADER
9098 && dwg->num_objects)
9099 {
9100 dwg->num_objects--;
9101 free (obj->tio.object->tio.BLOCK_HEADER);
9102 obj = &dwg->object[0];
9103 _obj = obj->tio.object->tio.APPID;
9104 LOG_TRACE ("Reuse existing BLOCK_HEADER.*Model_Space %X [0]\n",
9105 pair->value.u)
9106 }
9107 dwg_add_handle (&obj->handle, 0, pair->value.u, obj);
9108 LOG_TRACE ("%s.handle = " FORMAT_H " [H 5]\n", name,
9109 ARGS_H (obj->handle));
9110 if (ctrl_id)
9111 {
9112 // add to ctrl "entries" HANDLE_VECTOR
9113 Dwg_Object_BLOCK_CONTROL *_ctrl
9114 = dwg->object[ctrl_id].tio.object->tio.BLOCK_CONTROL;
9115 BITCODE_H *hdls = NULL;
9116 BITCODE_BL num_entries = 0;
9117
9118 if ((int)i < 0)
9119 i = 0;
9120 dwg_dynapi_entity_value (_ctrl, ctrlname, "num_entries",
9121 &num_entries, NULL);
9122 if (i >= num_entries)
9123 {
9124 // DXF often lies about num_entries, skipping defaults
9125 // e.g. BLOCK_CONTROL contains mspace+pspace in DXF, but in
9126 // the DWG they are extra. But this is fixed at case 2, not
9127 // here.
9128 LOG_TRACE ("Misleading %s.num_entries %d for %dth entry\n",
9129 ctrlname, num_entries, i);
9130 i = num_entries;
9131 num_entries++;
9132 dwg_dynapi_entity_set_value (
9133 _ctrl, ctrlname, "num_entries", &num_entries, 0);
9134 LOG_TRACE ("%s.num_entries = %d [BL 70]\n", ctrlname,
9135 num_entries);
9136 }
9137 dwg_dynapi_entity_value (_ctrl, ctrlname, "entries", &hdls,
9138 NULL);
9139 if (!hdls)
9140 hdls = (BITCODE_H *)xcalloc (num_entries,
9141 sizeof (Dwg_Object_Ref *));
9142 else
9143 hdls = (BITCODE_H *)realloc (
9144 hdls, num_entries * sizeof (Dwg_Object_Ref *));
9145 if (pair->value.u && !hdls)
9146 goto invalid_dxf;
9147 hdls[i] = dwg_add_handleref (dwg, 2, pair->value.u, obj);
9148 dwg_dynapi_entity_set_value (_ctrl, ctrlname, "entries", &hdls,
9149 0);
9150 LOG_TRACE ("%s.%s[%d] = " FORMAT_REF " [H* 0]\n", ctrlname,
9151 "entries", i, ARGS_REF (hdls[i]));
9152 }
9153 }
9154 break;
9155 case 8:
9156 if (is_entity && pair->value.s)
9157 {
9158 BITCODE_H handle = find_tablehandle (dwg, pair);
9159 if (!handle)
9160 {
9161 obj_hdls = array_push (obj_hdls, "layer", pair->value.s,
9162 obj->tio.object->objid);
9163 LOG_TRACE ("%s.layer: name %s -> H later\n", obj->name,
9164 pair->value.s)
9165 }
9166 else
9167 {
9168 dwg_dynapi_common_set_value (_obj, "layer", &handle, 1);
9169 LOG_TRACE ("%s.layer = %s " FORMAT_REF " [H 8]\n", name,
9170 pair->value.s, ARGS_REF (handle));
9171 }
9172 break;
9173 }
9174 // fall through
9175 case 100: // for nested structs
9176 if (pair->code == 100 && pair->value.s)
9177 {
9178 strncpy (subclass, pair->value.s, 79);
9179 subclass[79] = '\0';
9180 // set the real objname
9181 if (strEQc (obj->name, "DIMENSION_ANG2LN")
9182 || strEQc (obj->name, "DIMENSION"))
9183 {
9184 // we rather checked the flag before
9185 if (strEQc (subclass, "AcDbRotatedDimension"))
9186 {
9187 obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_LINEAR;
9188 obj->name = (char *)"DIMENSION_LINEAR";
9189 obj->dxfname = strdup (obj->name);
9190 strcpy (name, obj->name);
9191 LOG_TRACE ("change type to %s\n", name);
9192 }
9193 else if (strEQc (subclass, "AcDbAlignedDimension"))
9194 {
9195 // could be DIMENSION_LINEAR also. changed later on those
9196 // new pairs
9197 obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_ALIGNED;
9198 obj->name = (char *)"DIMENSION_ALIGNED";
9199 obj->dxfname = strdup (obj->name);
9200 strcpy (name, obj->name);
9201 LOG_TRACE ("change type to %s\n", name);
9202 }
9203 else if (strEQc (subclass, "AcDbOrdinateDimension"))
9204 {
9205 obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_ORDINATE;
9206 obj->name = (char *)"DIMENSION_ORDINATE";
9207 obj->dxfname = strdup (obj->name);
9208 strcpy (name, obj->name);
9209 LOG_TRACE ("change type to %s\n", name);
9210 }
9211 else if (strEQc (subclass, "AcDbDiametricDimension"))
9212 {
9213 obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_DIAMETER;
9214 obj->name = (char *)"DIMENSION_DIAMETER";
9215 obj->dxfname = strdup (obj->name);
9216 strcpy (name, obj->name);
9217 LOG_TRACE ("change type to %s\n", name);
9218 }
9219 else if (strEQc (subclass, "AcDbRadialDimension"))
9220 {
9221 UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_RADIUS)
9222 }
9223 else if (strEQc (subclass, "AcDb3PointAngularDimension"))
9224 {
9225 UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ANG3PT)
9226 }
9227 }
9228 if (strEQc (obj->name, "DIMENSION_ALIGNED")
9229 && strEQc (subclass, "AcDbRotatedDimension"))
9230 {
9231 UPGRADE_ENTITY (DIMENSION_ALIGNED, DIMENSION_LINEAR)
9232 }
9233 // set the real objname
9234 else if (strEQc (obj->name, "POLYLINE_2D"))
9235 {
9236 if (strEQc (subclass, "AcDb3dPolyline"))
9237 {
9238 UPGRADE_ENTITY (POLYLINE_2D, POLYLINE_3D)
9239 }
9240 else if (strEQc (subclass, "AcDbPolyFaceMesh"))
9241 {
9242 UPGRADE_ENTITY (POLYLINE_2D, POLYLINE_PFACE)
9243 }
9244 else if (strEQc (subclass, "AcDbPolygonMesh"))
9245 {
9246 UPGRADE_ENTITY (POLYLINE_2D, POLYLINE_MESH)
9247 }
9248 }
9249 else if (strEQc (obj->name, "VERTEX_2D"))
9250 {
9251 if (strEQc (subclass, "AcDb3dPolylineVertex"))
9252 {
9253 UPGRADE_ENTITY (VERTEX_2D, VERTEX_3D)
9254 }
9255 else if (strEQc (subclass, "AcDbPolyFaceMeshVertex"))
9256 { // _MESH or _PFACE:
9257 Dwg_Object_Ref *owner = obj->tio.entity->ownerhandle;
9258 Dwg_Object *parent = dwg_ref_object (dwg, owner);
9259 if (parent
9260 && parent->fixedtype == DWG_TYPE_POLYLINE_PFACE)
9261 {
9262 UPGRADE_ENTITY (VERTEX_2D, VERTEX_PFACE)
9263 }
9264 else
9265 { // AcDbPolygonMesh
9266 UPGRADE_ENTITY (VERTEX_2D, VERTEX_MESH)
9267 }
9268 }
9269 else if (strEQc (subclass, "AcDbFaceRecord"))
9270 {
9271 UPGRADE_ENTITY (VERTEX_2D, VERTEX_PFACE_FACE)
9272 }
9273 }
9274 else if (strEQc (obj->name, "INSERT")
9275 && strEQc (subclass, "AcDbMInsertBlock"))
9276 {
9277 UPGRADE_ENTITY (INSERT, MINSERT)
9278 }
9279
9280 // When we have all proper types, check proper subclasses.
9281 // If the subclass is allowed in this object.
9282 if (!dwg_has_subclass (obj->name, subclass))
9283 {
9284 if (is_type_stable (obj->fixedtype))
9285 {
9286 LOG_ERROR ("FIXME Unknown subclass %s in object %s", subclass, obj->name);
9287 return NULL;
9288 }
9289 else
9290 {
9291 LOG_WARN ("TODO Unknown subclass %s in object %s", subclass, obj->name);
9292 }
9293 }
9294 if (strEQc (subclass, "AcDbDetailViewStyle")
9295 && obj->fixedtype != DWG_TYPE_DETAILVIEWSTYLE)
9296 {
9297 LOG_ERROR ("Invalid subclass %s in object %s", subclass, obj->name);
9298 return NULL;
9299 }
9300
9301 // with PERSUBENTMGR
9302 if (obj->fixedtype == DWG_TYPE_PERSUBENTMGR
9303 && strEQc (subclass, "AcDbPersSubentManager"))
9304 {
9305 dxf_free_pair (pair);
9306 pair = dxf_read_pair (dat);
9307 pair = add_PERSUBENTMGR (obj, dat, pair); // NULL for success
9308 if (!pair)
9309 goto next_pair;
9310 else
9311 goto start_loop; /* failure */
9312 }
9313 // with ASSOCDEPENDENCY or ACDBASSOCGEOMDEPENDENCY
9314 else if (strstr (obj->name, "ASSOC")
9315 && strstr (obj->name, "DEPENDENCY")
9316 && strEQc (subclass, "AcDbAssocDependency"))
9317 {
9318 dxf_free_pair (pair);
9319 pair = add_ASSOCDEPENDENCY (obj, dat); // NULL for success
9320 if (!pair)
9321 goto next_pair;
9322 else
9323 goto start_loop; /* failure */
9324 }
9325 // with ASSOC2DCONSTRAINTGROUP, ASSOCNETWORK, ASSOCACTION
9326 else if (strstr (obj->name, "ASSOC")
9327 && strEQc (subclass, "AcDbAssocAction"))
9328 {
9329 dxf_free_pair (pair);
9330 pair = dxf_read_pair (dat);
9331 pair = add_ASSOCACTION (obj, dat, pair); // NULL for success
9332 if (!pair)
9333 {
9334 // TODO: yet unsupported
9335 if (strEQc (name, "ASSOC2DCONSTRAINTGROUP"))
9336 return dxf_read_pair (dat);
9337 else
9338 goto next_pair;
9339 }
9340 else
9341 goto start_loop; /* failure */
9342 }
9343 else if (strstr (obj->name, "ASSOC")
9344 && strEQc (subclass, "AcDbAssocNetwork"))
9345 {
9346 dxf_free_pair (pair);
9347 pair = dxf_read_pair (dat);
9348 LOG_TRACE ("add_ASSOCNETWORK\n")
9349 pair = add_ASSOCNETWORK (obj, dat, pair); // NULL for success
9350 if (!pair)
9351 goto next_pair;
9352 else
9353 goto start_loop; /* failure */
9354 }
9355 // strict subclasses (functable?)
9356 #define CHK_SUBCLASS(cppname, addmethod) \
9357 if (strEQc (subclass, #cppname)) \
9358 { \
9359 dxf_free_pair (pair); \
9360 LOG_TRACE ("add_" #addmethod "\n") \
9361 pair = add_##addmethod (obj, dat); /* NULL for success */ \
9362 if (!pair) \
9363 goto next_pair; \
9364 else \
9365 goto start_loop; /* failure */ \
9366 }
9367 else CHK_SUBCLASS (AcDbBlockParameter, AcDbBlockParameter)
9368 else CHK_SUBCLASS (AcDbBlockGripExpr, AcDbBlockGripExpr)
9369 else CHK_SUBCLASS (AcDbBlockAlignmentGrip, BLOCKALIGNMENTGRIP)
9370 else CHK_SUBCLASS (AcDbBlockLinearGrip, BLOCKALIGNMENTGRIP)
9371 else CHK_SUBCLASS (AcDbBlockFlipGrip, BLOCKFLIPGRIP)
9372 else CHK_SUBCLASS (AcDbRenderEnvironment, RENDERENVIRONMENT)
9373 else CHK_SUBCLASS (AcDbRenderGlobal, RENDERGLOBAL)
9374 else CHK_SUBCLASS (AcDbRenderEntry, RENDERENTRY)
9375 else CHK_SUBCLASS (AcDbRenderSettings, RENDERSETTINGS)
9376 // more DYNBLOCKs
9377 #define else_do_strict_subclass(SUBCLASS) \
9378 else if (strEQc (subclass, #SUBCLASS)) \
9379 { \
9380 dxf_free_pair (pair); \
9381 LOG_TRACE ("add_" #SUBCLASS "\n") \
9382 pair = add_##SUBCLASS (obj, dat); \
9383 if (!pair) /* NULL for success */ \
9384 goto next_pair; \
9385 else \
9386 goto start_loop; /* failure */ \
9387 }
9388
9389 else_do_strict_subclass (AcDbBlock1PtParameter)
9390 else_do_strict_subclass (AcDbBlock2PtParameter)
9391 else_do_strict_subclass (AcDbBlockAction)
9392 else_do_strict_subclass (AcDbBlockActionWithBasePt)
9393 else_do_strict_subclass (AcDbBlockFlipAction)
9394 else_do_strict_subclass (AcDbBlockMoveAction)
9395 else_do_strict_subclass (AcDbBlockRotationAction)
9396 else_do_strict_subclass (AcDbBlockScaleAction)
9397 else_do_strict_subclass (AcDbBlockStretchAction)
9398 else_do_strict_subclass (AcDbBlockRotationParameter)
9399 }
9400 break;
9401 case 101:
9402 if (pair->value.s && strEQc (pair->value.s, "Embedded Object"))
9403 in_embedobj = 1;
9404 break;
9405 case 102:
9406 if (pair->value.s && strEQc (pair->value.s, "{ACAD_XDICTIONARY"))
9407 in_xdict = 1;
9408 else if (pair->value.s && strEQc (pair->value.s, "{ACAD_REACTORS"))
9409 in_reactors = 1;
9410 else if (ctrl_id && pair->value.s
9411 && strEQc (pair->value.s, "{BLKREFS"))
9412 in_blkrefs = 1; // unique handle 331
9413 else if (pair->value.s && strEQc (pair->value.s, "}"))
9414 in_reactors = in_xdict = in_blkrefs = 0;
9415 else if (pair->value.s && strEQc (name, "XRECORD"))
9416 pair = add_xdata (dat, obj, pair);
9417 else
9418 LOG_WARN ("Unknown DXF code 102 %s in %s", pair->value.s, name)
9419 break;
9420 case 331:
9421 if (ctrl_id && in_blkrefs) // BLKREFS TODO
9422 {
9423 BITCODE_H *inserts = NULL;
9424 BITCODE_H hdl;
9425 BITCODE_RL num_inserts;
9426 dwg_dynapi_entity_value (_obj, obj->name, "num_inserts",
9427 &num_inserts, 0);
9428 if (curr_inserts)
9429 dwg_dynapi_entity_value (_obj, obj->name, "inserts", &inserts,
9430 0);
9431 if (curr_inserts + 1 > num_inserts)
9432 {
9433 LOG_HANDLE (" extending %s.num_inserts %d < %d\n",
9434 obj->name, num_inserts, curr_inserts + 1);
9435 num_inserts = curr_inserts + 1;
9436 dwg_dynapi_entity_set_value (_obj, obj->name, "num_inserts",
9437 &num_inserts, 0);
9438 }
9439 if (inserts)
9440 inserts = (BITCODE_H *)realloc (
9441 inserts, num_inserts * sizeof (BITCODE_H));
9442 else
9443 inserts
9444 = (BITCODE_H *)xcalloc (num_inserts, sizeof (BITCODE_H));
9445 if (num_inserts && !inserts)
9446 goto invalid_dxf;
9447 dwg_dynapi_entity_set_value (_obj, obj->name, "inserts",
9448 &inserts, 0);
9449 hdl = dwg_add_handleref (dwg, 4, pair->value.u, NULL); // absolute
9450 LOG_TRACE ("%s.inserts[%d] = " FORMAT_REF " [H* 331]\n",
9451 obj->name, curr_inserts, ARGS_REF (hdl));
9452 inserts[curr_inserts++] = hdl;
9453 break;
9454 }
9455 else if (pair->code == 331 && obj->fixedtype == DWG_TYPE_LAYOUT)
9456 {
9457 Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
9458 o->active_viewport
9459 = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
9460 LOG_TRACE ("%s.active_viewport = " FORMAT_REF " [H 331]\n",
9461 obj->name, ARGS_REF (o->active_viewport));
9462 break;
9463 }
9464 // fall through
9465 case 330:
9466 if (in_reactors)
9467 {
9468 BITCODE_BL num = is_entity ? obj->tio.entity->num_reactors
9469 : obj->tio.object->num_reactors;
9470 BITCODE_H reactor = dwg_add_handleref (dwg, 4, pair->value.u,
9471 NULL); // always abs
9472 LOG_TRACE ("%s.reactors[%d] = " FORMAT_REF " [H* 330]\n", name,
9473 num, ARGS_REF (reactor));
9474 if (is_entity)
9475 {
9476 obj->tio.entity->reactors
9477 = (BITCODE_H *)realloc (obj->tio.entity->reactors,
9478 (num + 1) * sizeof (BITCODE_H));
9479 obj->tio.entity->reactors[num] = reactor;
9480 obj->tio.entity->num_reactors++;
9481 }
9482 else
9483 {
9484 obj->tio.object->reactors
9485 = (BITCODE_H *)realloc (obj->tio.object->reactors,
9486 (num + 1) * sizeof (BITCODE_H));
9487 obj->tio.object->reactors[num] = reactor;
9488 obj->tio.object->num_reactors++;
9489 }
9490 }
9491 else if (pair->code == 330 && obj->fixedtype == DWG_TYPE_LAYOUT
9492 && obj->tio.object->ownerhandle)
9493 {
9494 Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
9495 o->block_header
9496 = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
9497 LOG_TRACE ("%s.block_header = " FORMAT_REF " [H 330]\n",
9498 obj->name, ARGS_REF (o->block_header));
9499 }
9500 // valid ownerhandle, if not XRECORD with an ownerhandle already
9501 else if (pair->code == 330
9502 && (obj->fixedtype != DWG_TYPE_XRECORD
9503 || !obj->tio.object->ownerhandle))
9504 {
9505 BITCODE_H owh;
9506 if (is_obj_absowner (obj))
9507 owh = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
9508 else // relative
9509 owh = dwg_add_handleref (dwg, 4, pair->value.u, obj);
9510 if (is_entity)
9511 obj->tio.entity->ownerhandle = owh;
9512 else
9513 obj->tio.object->ownerhandle = owh;
9514 LOG_TRACE ("%s.ownerhandle = " FORMAT_REF " [H 330]\n", name,
9515 ARGS_REF (owh));
9516 }
9517 break;
9518 case 350: // DICTIONARY softhandle
9519 case 360: // {ACAD_XDICTIONARY or some hardowner
9520 if (pair->code == 360 && in_xdict)
9521 {
9522 BITCODE_H xdic = dwg_add_handleref (dwg, 3, pair->value.u, obj);
9523 if (is_entity)
9524 {
9525 obj->tio.entity->xdicobjhandle = xdic;
9526 obj->tio.entity->is_xdic_missing = 0;
9527 }
9528 else
9529 {
9530 obj->tio.object->xdicobjhandle = xdic;
9531 obj->tio.object->is_xdic_missing = 0;
9532 }
9533 LOG_TRACE ("%s.xdicobjhandle = " FORMAT_REF " [H 360]\n", name,
9534 ARGS_REF (xdic));
9535 break;
9536 }
9537 // // DICTIONARY or DICTIONARYWDFLT, but not DICTIONARYVAR
9538 else if (memBEGINc (name, "DICTIONARY")
9539 && strNE (name, "DICTIONARYVAR"))
9540 {
9541 add_dictionary_itemhandles (obj, pair, text);
9542 break;
9543 }
9544 else if (pair->code == 360 && // hardowner, not soft
9545 (obj->fixedtype == DWG_TYPE_IMAGE
9546 || obj->fixedtype == DWG_TYPE_WIPEOUT))
9547 {
9548 BITCODE_H ref = dwg_add_handleref (dwg, 3, pair->value.u, obj);
9549 dwg_dynapi_entity_set_value (_obj, obj->name, "imagedefreactor",
9550 ref, 0);
9551 LOG_TRACE ("%s.imagedefreactor = " FORMAT_REF " [H %d]\n", name,
9552 ARGS_REF (ref), pair->code);
9553 break;
9554 }
9555 // fall through
9556 case 340:
9557 if (pair->code == 340 && strEQc (name, "GROUP"))
9558 {
9559 Dwg_Object_GROUP *o = obj->tio.object->tio.GROUP;
9560 BITCODE_H hdl = dwg_add_handleref (dwg, 5, pair->value.u, obj);
9561 LOG_TRACE ("GROUP.groups[%d] = " FORMAT_REF " [H* 340]\n",
9562 o->num_groups, ARGS_REF (hdl));
9563 o->groups = (BITCODE_H *)realloc (
9564 o->groups, (o->num_groups + 1) * sizeof (BITCODE_H));
9565 o->groups[o->num_groups] = hdl;
9566 o->num_groups++;
9567 break;
9568 }
9569 // fall through
9570 case 341:
9571 if (pair->code == 341 && strEQc (name, "VIEWPORT"))
9572 {
9573 Dwg_Entity_VIEWPORT *o = obj->tio.entity->tio.VIEWPORT;
9574 int code = dwg->header.version >= R_2004 ? 4 : 5;
9575 BITCODE_H hdl
9576 = dwg_add_handleref (dwg, code, pair->value.u, obj);
9577 LOG_TRACE ("VIEWPORT.frozen_layers[%d] = " FORMAT_REF
9578 " [H* 341]\n",
9579 o->num_frozen_layers, ARGS_REF (hdl));
9580 o->frozen_layers = (BITCODE_H *)realloc (
9581 o->frozen_layers,
9582 (o->num_frozen_layers + 1) * sizeof (BITCODE_H));
9583 o->frozen_layers[o->num_frozen_layers] = hdl;
9584 o->num_frozen_layers++;
9585 break;
9586 }
9587 // fall through
9588 case 2:
9589 if (ctrl_id && pair->code == 2)
9590 {
9591 dwg_dynapi_entity_set_value (_obj, obj->name, "name",
9592 &pair->value, 1);
9593 LOG_TRACE ("%s.name = %s [T 2]\n", name, pair->value.s);
9594 if (!pair->value.s)
9595 break;
9596 assert (i_p); // needs ctrl_id
9597 *i_p = i + 1;
9598 if (strEQc (name, "BLOCK_RECORD"))
9599 {
9600 // seperate mspace and pspace into its own fields
9601 Dwg_Object_BLOCK_CONTROL *_ctrl
9602 = ctrl->tio.object->tio.BLOCK_CONTROL;
9603 if (!strcasecmp (pair->value.s, "*Paper_Space"))
9604 {
9605 const char *f = "paper_space";
9606 _ctrl->paper_space
9607 = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9608 LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9609 ARGS_REF (_ctrl->paper_space));
9610 dwg->header_vars.BLOCK_RECORD_PSPACE
9611 = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9612 // move out of entries
9613 if (move_out_BLOCK_CONTROL (obj, _ctrl, f))
9614 *i_p = i;
9615 }
9616 else if (!strcasecmp (pair->value.s, "*Model_Space"))
9617 {
9618 const char *f = "model_space";
9619 _ctrl->model_space
9620 = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9621 LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9622 ARGS_REF (_ctrl->model_space));
9623 dwg->header_vars.BLOCK_RECORD_MSPACE
9624 = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9625 // move out of entries
9626 if (move_out_BLOCK_CONTROL (obj, _ctrl, f))
9627 *i_p = i;
9628 }
9629 }
9630 else if (strEQc (name, "LTYPE"))
9631 {
9632 // seperate bylayer and byblock into its own fields
9633 Dwg_Object_LTYPE_CONTROL *_ctrl
9634 = ctrl->tio.object->tio.LTYPE_CONTROL;
9635 if (!strcasecmp (pair->value.s, "ByLayer"))
9636 {
9637 const char *f = "bylayer";
9638 _ctrl->bylayer
9639 = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9640 LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9641 ARGS_REF (_ctrl->bylayer));
9642 dwg->header_vars.LTYPE_BYLAYER
9643 = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9644 // move out of entries
9645 if (move_out_LTYPE_CONTROL (obj, _ctrl, f))
9646 *i_p = i;
9647 }
9648 else if (!strcasecmp (pair->value.s, "ByBlock"))
9649 {
9650 const char *f = "byblock";
9651 _ctrl->byblock
9652 = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9653 LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9654 ARGS_REF (_ctrl->byblock));
9655 dwg->header_vars.LTYPE_BYBLOCK
9656 = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9657 // move out of entries
9658 if (move_out_LTYPE_CONTROL (obj, _ctrl, f))
9659 *i_p = i;
9660 }
9661 }
9662 break;
9663 }
9664 if (pair->code == 2 && strEQc (name, "MLINE"))
9665 {
9666 // ignore name of mlinestyle, already set by ->mlinestyle
9667 break;
9668 }
9669 if (pair->code == 2 && dwg_obj_is_3dsolid (obj))
9670 {
9671 BITCODE_BL revision_major;
9672 BITCODE_BS revision_minor1;
9673 BITCODE_BS revision_minor2;
9674 BITCODE_RC revision_bytes[9];
9675 // no malloc, it is copied into the dwg. but it needs to be large
9676 // enough, pair->value.s might be smaller on corrupt DXF's. Also
9677 // we null-terminate it.
9678 char revision_guid[39];
9679 char *p = &revision_guid[0];
9680 unsigned u[3];
9681 if (!pair->value.s)
9682 {
9683 LOG_ERROR ("Invalid %s.revision_guid %s", obj->name,
9684 revision_guid);
9685 break;
9686 }
9687 // "{00000100-0100-00CA-D300-80010A7B10C3}"
9688 strncpy (revision_guid, pair->value.s, 38);
9689 revision_guid[38] = '\0';
9690 if (!dwg_dynapi_entity_set_value (
9691 _obj, obj->name, "revision_guid[39]", revision_guid, 0))
9692 break;
9693 if (revision_guid[0] != '{' || /* 8 */
9694 revision_guid[9] != '-' || /* 4 */
9695 revision_guid[14] != '-' || /* 4 */
9696 revision_guid[19] != '-' || /* 4 */
9697 revision_guid[24] != '-' || /* 12 */
9698 revision_guid[37] != '}')
9699 {
9700 LOG_ERROR ("Invalid %s.revision_guid %s", obj->name,
9701 revision_guid);
9702 break;
9703 }
9704 sscanf (p, "{%8" PRIx32 "-%4X-%4X-%4X-", &revision_major, &u[0],
9705 &u[1], &u[2]);
9706 revision_minor1 = (BITCODE_BS)u[0];
9707 revision_minor2 = (BITCODE_BS)u[1];
9708 p += 20;
9709 sscanf (p, SCANF_2X, &revision_bytes[0]);
9710 p += 2;
9711 sscanf (p, SCANF_2X, &revision_bytes[1]);
9712 p += 3;
9713 for (int _i = 2; _i < 8; _i++)
9714 {
9715 sscanf (p, SCANF_2X, &revision_bytes[_i]);
9716 p += 2;
9717 }
9718 revision_bytes[8]
9719 = '\0'; // insist on an ending 0 byte, even if never used.
9720 dwg_dynapi_entity_set_value (_obj, obj->name, "revision_major",
9721 &revision_major, 0);
9722 dwg_dynapi_entity_set_value (_obj, obj->name, "revision_minor1",
9723 &revision_minor1, 0);
9724 dwg_dynapi_entity_set_value (_obj, obj->name, "revision_minor2",
9725 &revision_minor2, 0);
9726 dwg_dynapi_entity_set_value (
9727 _obj, obj->name, "revision_bytes[9]", revision_bytes, 0);
9728 break;
9729 }
9730 // fall through
9731 case 70:
9732 if (ctrl_id && pair->code == 70)
9733 {
9734 BITCODE_B bit;
9735 ;
9736 flag = pair->value.i | 64;
9737 dwg_dynapi_entity_set_value (_obj, obj->name, "flag", &flag, 1);
9738 LOG_TRACE ("%s.flag = %d [RC 70]\n", name, pair->value.i);
9739 if (obj->fixedtype == DWG_TYPE_STYLE)
9740 {
9741
9742 #define SET_CTRL_BIT(b, bnam) \
9743 bit = flag & b ? 1 : 0; \
9744 if (bit) \
9745 { \
9746 dwg_dynapi_entity_set_value (_obj, obj->name, #bnam, &bit, 1); \
9747 LOG_TRACE ("%s.%s = %d [B]\n", name, #bnam, bit); \
9748 }
9749
9750 SET_CTRL_BIT (1, is_vertical);
9751 SET_CTRL_BIT (4, is_shape);
9752 }
9753 else if (obj->fixedtype == DWG_TYPE_LAYER)
9754 {
9755 SINCE (R_2000)
9756 {
9757 SET_CTRL_BIT (1, frozen);
9758 bit = flag & 2 ? 0 : 1; // reverse
9759 if (bit)
9760 {
9761 dwg_dynapi_entity_set_value (_obj, obj->name, "on",
9762 &bit, 1);
9763 LOG_TRACE ("%s.%s = %d [B]\n", name, "on", bit);
9764 }
9765 SET_CTRL_BIT (4, frozen_in_new);
9766 SET_CTRL_BIT (8, locked);
9767 SET_CTRL_BIT (32768, plotflag);
9768 }
9769 else
9770 {
9771 SET_CTRL_BIT (1, frozen);
9772 SET_CTRL_BIT (2, frozen_in_new);
9773 SET_CTRL_BIT (4, locked);
9774 }
9775 }
9776 else if (obj->fixedtype == DWG_TYPE_BLOCK_HEADER)
9777 {
9778 SET_CTRL_BIT (1, anonymous);
9779 SET_CTRL_BIT (2, hasattrs);
9780 SET_CTRL_BIT (4, blkisxref);
9781 SET_CTRL_BIT (8, xrefoverlaid);
9782 SET_CTRL_BIT (32, loaded_bit);
9783 }
9784 else if (obj->fixedtype == DWG_TYPE_VIEW)
9785 {
9786 SET_CTRL_BIT (1, is_pspace);
9787 }
9788 else if (obj->fixedtype == DWG_TYPE_DIMSTYLE)
9789 {
9790 SET_CTRL_BIT (1, flag0);
9791 }
9792 else if (obj->fixedtype == DWG_TYPE_VX_TABLE_RECORD)
9793 {
9794 // also set via 290
9795 SET_CTRL_BIT (2, is_on);
9796 }
9797 break;
9798 }
9799 else if (pair->code == 70 && obj->fixedtype == DWG_TYPE_LAYOUT)
9800 {
9801 Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
9802 if (strEQc (subclass,
9803 "AcDbPlotSettings")) // todo: embedded struct
9804 {
9805 o->plotsettings.plot_flags = pair->value.i;
9806 LOG_TRACE ("LAYOUT.plotsettings.plot_flags = 0x%x [BSx 70]",
9807 pair->value.i);
9808 }
9809 else if (strEQc (subclass, "AcDbLayout"))
9810 {
9811 o->layout_flags = pair->value.u;
9812 LOG_TRACE ("LAYOUT.layout_flags = 0x%x [BSx 70]",
9813 pair->value.u);
9814 }
9815 else
9816 {
9817 LOG_WARN ("Unhandled LAYOUT.70 in subclass %s", subclass);
9818 o->layout_flags = pair->value.u;
9819 LOG_TRACE ("LAYOUT.layout_flags = 0x%x [BSx 70]",
9820 pair->value.u);
9821 }
9822 break;
9823 }
9824 else if (pair->code == 70 && obj->fixedtype == DWG_TYPE_LWPOLYLINE)
9825 {
9826 Dwg_Entity_LWPOLYLINE *o = obj->tio.entity->tio.LWPOLYLINE;
9827 o->flag = pair->value.i;
9828 // 1 => 512 closed
9829 // 128: plinegen
9830 if (o->flag & 1)
9831 o->flag = (o->flag - 1) + 512;
9832 LOG_TRACE ("LWPOLYLINE.flag => %d [BS 70]\n", flag);
9833 break;
9834 }
9835 else if (pair->code == 70
9836 && strEQc (subclass, "AcDbModelDocViewStyle"))
9837 {
9838 BITCODE_BS ver = pair->value.i;
9839 LOG_TRACE ("%s.mdoc_class_version = %d [BS %d]\n", name,
9840 pair->value.i, pair->code);
9841 dwg_dynapi_entity_set_value (_obj, obj->name,
9842 "mdoc_class_version", &ver, is_tu);
9843 break;
9844 }
9845 else if (pair->code == 70
9846 && (strEQc (subclass, "AcDbSectionViewStyle")
9847 || strEQc (subclass, "AcDbDetailViewStyle")))
9848 {
9849 BITCODE_BS ver = pair->value.i;
9850 LOG_TRACE ("%s.class_version = %d [BS %d]\n", name,
9851 pair->value.i, pair->code);
9852 dwg_dynapi_entity_set_value (_obj, obj->name, "class_version",
9853 &ver, is_tu);
9854 break;
9855 }
9856 else if (pair->code == 70
9857 && obj->fixedtype == DWG_TYPE_DIMENSION_ANG2LN)
9858 {
9859 Dwg_Entity_DIMENSION_ANG2LN *o
9860 = obj->tio.entity->tio.DIMENSION_ANG2LN;
9861 o->flag = o->flag1 = pair->value.i;
9862 LOG_TRACE ("DIMENSION.flag = %d [RC 70]\n", pair->value.i);
9863 o->flag1 &= 0xE0; /* clear the upper flag bits, and fix them: */
9864 o->flag1 = (o->flag1 & 0x80) ? o->flag1 & 0x7F : o->flag1 | 1;
9865 o->flag1 = (o->flag1 & 0x20) ? o->flag1 | 2 : o->flag1 & 0xDF;
9866 LOG_TRACE ("DIMENSION.flag1 => %d [RC]\n", o->flag1);
9867 // Skip this flag logic, it is unreliable. Detecting subclasses
9868 // is far better.
9869 switch (o->flag & 31)
9870 {
9871 case 0: // rotated, horizontal or vertical
9872 LOG_TRACE ("Looks like %s\n", "DIMENSION_LINEAR");
9873 // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_LINEAR);
9874 break;
9875 case 1:
9876 LOG_TRACE ("Looks like %s\n", "DIMENSION_ALIGNED");
9877 // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ALIGNED);
9878 break;
9879 case 2: // already?
9880 LOG_TRACE ("Looks like %s\n", "DIMENSION_ANG2LN");
9881 // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ANG2LN);
9882 break;
9883 case 3:
9884 LOG_TRACE ("Looks like %s\n", "DIMENSION_DIAMETER");
9885 // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_DIAMETER);
9886 break;
9887 case 4:
9888 LOG_TRACE ("Looks like %s\n", "DIMENSION_RADIUS");
9889 // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_RADIUS);
9890 break;
9891 case 5:
9892 LOG_TRACE ("Looks like %s\n", "DIMENSION_ANG3PT");
9893 // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ANG3PT);
9894 break;
9895 case 6:
9896 LOG_TRACE ("Looks like DIMENSION_LINEAR\n");
9897 // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ORDINATE);
9898 break;
9899 default:
9900 LOG_ERROR ("Invalid DIMENSION.flag %d", o->flag & 31);
9901 error |= DWG_ERR_INVALIDTYPE;
9902 break;
9903 }
9904 break;
9905 }
9906 // fall through
9907 case 420: // color.rgb's
9908 case 421:
9909 case 422:
9910 case 423:
9911 case 424:
9912 case 425:
9913 case 426:
9914 case 427:
9915 case 428:
9916 // note that there is a DIMSTYLE.DIMTFILL with rgb 428. so far I only
9917 // found index 70, not rgb 428
9918 if (pair->code >= 420 && pair->code <= 428)
9919 {
9920 const char *fname = NULL;
9921 if (pair->code == 420 && strEQc (name, "LAYER"))
9922 fname = "color";
9923 else if (pair->code == 421 && strEQc (name, "LIGHT"))
9924 fname = "color";
9925 else if (pair->code == 421
9926 && (strEQc (name, "VPORT") || strEQc (name, "VIEWPORT")
9927 || strEQc (name, "VIEW")))
9928 fname = "ambient_color";
9929 else if (pair->code == 421 && strEQc (name, "MTEXT"))
9930 fname = "bg_fill_color";
9931 else if (pair->code == 420 && strEQc (name, "MLINESTYLE"))
9932 // TODO or lines[].color
9933 fname = "fill_color";
9934 else if (pair->code == 420 && strEQc (name, "VISUALSTYLE"))
9935 break; // ignore. always index 5
9936 else if (pair->code == 421 && strEQc (name, "VISUALSTYLE"))
9937 fname = "face_mono_color";
9938 else if (pair->code == 422 && strEQc (name, "VISUALSTYLE"))
9939 fname = "edge_intersection_color";
9940 else if (pair->code == 423 && strEQc (name, "VISUALSTYLE"))
9941 fname = "edge_obscured_color";
9942 else if (pair->code == 424 && strEQc (name, "VISUALSTYLE"))
9943 fname = "edge_color";
9944 else if (pair->code == 425 && strEQc (name, "VISUALSTYLE"))
9945 fname = "edge_silhouette_color";
9946 else if (pair->code == 428 && strEQc (name, "DIMSTYLE"))
9947 fname = "DIMTFILL";
9948 else if (strEQc (name, "TABLE"))
9949 {
9950 BITCODE_BL table_flag
9951 = obj->tio.entity->tio.TABLE->table_flag_override;
9952 BITCODE_BL border_color = obj->tio.entity->tio.TABLE
9953 ->border_color_overrides_flag;
9954 if (pair->code == 421)
9955 {
9956 if (table_flag & 0x0800)
9957 fname = "title_row_fill_color";
9958 else if (table_flag & 0x01000)
9959 fname = "header_row_fill_color";
9960 else if (table_flag & 0x02000)
9961 fname = "data_row_fill_color";
9962 else if (border_color & 0x0008)
9963 fname = "title_vert_left_color";
9964 else if (border_color & 0x0200)
9965 fname = "header_vert_left_color";
9966 else if (border_color & 0x8000)
9967 fname = "data_vert_left_color";
9968 }
9969 else if (pair->code == 422)
9970 {
9971 if (table_flag & 0x0020)
9972 fname = "title_row_color";
9973 else if (table_flag & 0x0040)
9974 fname = "header_row_color";
9975 else if (table_flag & 0x0080)
9976 fname = "data_row_color";
9977 else if (border_color & 0x0001)
9978 fname = "title_horiz_top_color";
9979 else if (border_color & 0x0040)
9980 fname = "header_horiz_top_color";
9981 else if (border_color & 0x1000)
9982 fname = "data_horiz_top_color";
9983 }
9984 else if (pair->code == 423)
9985 {
9986 if (border_color & 0x0002)
9987 fname = "title_horiz_ins_color";
9988 else if (border_color & 0x0080)
9989 fname = "header_horiz_ins_color";
9990 else if (border_color & 0x2000)
9991 fname = "data_horiz_ins_color";
9992 }
9993 else if (pair->code == 424)
9994 {
9995 if (border_color & 0x0004)
9996 fname = "title_horiz_bottom_color";
9997 else if (border_color & 0x0100)
9998 fname = "header_horiz_bottom_color";
9999 else if (border_color & 0x4000)
10000 fname = "data_horiz_bottom_color";
10001 }
10002 else if (pair->code == 426)
10003 {
10004 if (border_color & 0x0010)
10005 fname = "title_vert_ins_color";
10006 else if (border_color & 0x0400)
10007 fname = "header_vert_ins_color";
10008 else if (border_color & 0x10000)
10009 fname = "data_vert_ins_color";
10010 }
10011 else if (pair->code == 427)
10012 {
10013 if (border_color & 0x0020)
10014 fname = "title_vert_right_color";
10015 else if (border_color & 0x0800)
10016 fname = "header_vert_right_color";
10017 else if (border_color & 0x20000)
10018 fname = "data_vert_right_color";
10019 }
10020 }
10021
10022 if (fname)
10023 {
10024 BITCODE_CMC color;
10025 dwg_dynapi_entity_value (_obj, obj->name, fname, &color,
10026 NULL);
10027 color.method = 0xc2;
10028 color.rgb = pair->value.l;
10029 color.rgb |= 0xc2000000;
10030 LOG_TRACE ("%s.%s.rgb = %08X [CMC %d]\n", name, fname,
10031 color.rgb, pair->code);
10032 dwg_dynapi_entity_set_value (_obj, obj->name, fname, &color,
10033 is_tu);
10034 break;
10035 }
10036 }
10037 // fall through
10038 default:
10039 object_default:
10040 if (pair->code >= 1000 && pair->code < 1999)
10041 add_eed (obj, obj->name, pair);
10042 else if (pair->code != 280 && strEQc (name, "XRECORD"))
10043 pair = add_xdata (dat, obj, pair);
10044 else if (pair->code == 310 && strEQc (obj->name, "BLOCK_HEADER"))
10045 {
10046 pair = add_block_preview (obj, dat, pair);
10047 goto start_loop;
10048 }
10049 else if (pair->code == 90 && obj->fixedtype == DWG_TYPE_OLE2FRAME)
10050 {
10051 Dwg_Entity_OLE2FRAME *o = obj->tio.entity->tio.OLE2FRAME;
10052 o->data_size = pair->value.l;
10053 o->data = (BITCODE_RC *)xcalloc (pair->value.l, 1);
10054 if (!o->data)
10055 {
10056 o->data_size = 0;
10057 goto invalid_dxf;
10058 }
10059 LOG_TRACE ("OLE2FRAME.data_size = %ld [BL 90]\n", pair->value.l);
10060 }
10061 else if (pair->code == 90 && obj->fixedtype == DWG_TYPE_PERSUBENTMGR)
10062 {
10063 pair = add_PERSUBENTMGR (obj, dat, pair); // NULL for success
10064 if (!pair)
10065 goto next_pair;
10066 else
10067 goto start_loop; /* failure */
10068 }
10069 else if ((pair->code == 71 || pair->code == 75 || pair->code == 1)
10070 && obj->fixedtype == DWG_TYPE_DIMASSOC)
10071 {
10072 pair = add_DIMASSOC (obj, dat, pair);
10073 // returns with 0
10074 if (pair != NULL && pair->code == 0)
10075 goto start_loop;
10076 else
10077 goto search_field;
10078 }
10079 else if ((pair->code == 8 || pair->code == 90)
10080 && obj->fixedtype == DWG_TYPE_LAYER_INDEX)
10081 {
10082 pair = add_LAYER_entry (obj, dat, pair);
10083 // returns with 0
10084 if (pair != NULL && pair->code == 0)
10085 goto start_loop;
10086 else
10087 goto search_field;
10088 }
10089 else if (pair->code == 91 && obj->fixedtype == DWG_TYPE_EVALUATION_GRAPH)
10090 {
10091 pair = add_EVAL_Node (obj, dat, pair);
10092 // returns with 0
10093 if (pair != NULL && pair->code == 0)
10094 goto start_loop;
10095 else
10096 goto search_field;
10097 }
10098 else if (pair->code == 310 && obj->fixedtype == DWG_TYPE_OLE2FRAME)
10099 {
10100 Dwg_Entity_OLE2FRAME *o = obj->tio.entity->tio.OLE2FRAME;
10101 unsigned len = strlen (pair->value.s);
10102 unsigned blen = len / 2;
10103 unsigned read;
10104 //const char *pos = pair->value.s;
10105 unsigned char *s = (unsigned char *)&o->data[written];
10106 assert (o->data);
10107 if (blen + written > o->data_size)
10108 {
10109 LOG_ERROR ("OLE2FRAME.data overflow: %u + written %u > "
10110 "data_size: %u",
10111 blen, written, o->data_size);
10112 goto invalid_dxf;
10113 }
10114 if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
10115 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
10116 written += read;
10117 LOG_TRACE ("OLE2FRAME.data += %u (%u/%u) [TF 310]\n", blen,
10118 written, o->data_size);
10119 }
10120 else if (pair->code == 1
10121 && ((strEQc (name, "_3DSOLID") || strEQc (name, "BODY")
10122 || strEQc (name, "REGION"))
10123 || strEQc (subclass, "AcDbModelerGeometry")))
10124 {
10125 j = 0;
10126 k = 0;
10127 // check if the object is valid
10128 if (!dwg_obj_is_3dsolid (obj))
10129 {
10130 LOG_ERROR ("%s not a 3DSOLID", name);
10131 goto invalid_dxf;
10132 }
10133 pair = add_3DSOLID_encr (obj, dat, pair);
10134 goto start_loop;
10135 }
10136 else if (pair->code == 1 && obj->fixedtype == DWG_TYPE_LAYOUT)
10137 {
10138 Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
10139 if (strEQc (subclass, "AcDbPlotSettings"))
10140 {
10141 const Dwg_DYNAPI_field *f = dwg_dynapi_entity_field (
10142 "PLOTSETTINGS", "printer_cfg_file");
10143 dwg_dynapi_field_set_value (dwg, &o->plotsettings, f,
10144 &pair->value, 1);
10145 LOG_TRACE ("%s.plotsettings.printer_cfg_file = %s [T 1]\n",
10146 obj->name, pair->value.s);
10147 }
10148 else if (strEQc (subclass, "AcDbLayout"))
10149 {
10150 dwg_dynapi_entity_set_value (_obj, obj->name, "layout_name",
10151 &pair->value, 1);
10152 LOG_TRACE ("%s.layout_name = %s [T 1]\n", obj->name,
10153 pair->value.s);
10154 }
10155 else
10156 LOG_WARN ("Unhandled LAYOUT.1 in subclass %s", subclass);
10157 goto next_pair;
10158 }
10159 else if (pair->code == 3 && obj->fixedtype == DWG_TYPE_MTEXT)
10160 {
10161 Dwg_Entity_MTEXT *o = obj->tio.entity->tio.MTEXT;
10162 unsigned len = strlen (pair->value.s);
10163 if (!o->text)
10164 {
10165 o->text = strdup (pair->value.s);
10166 written = len;
10167 LOG_TRACE ("MTEXT.text = %s (%u) [TV 3]\n", pair->value.s, len);
10168 }
10169 else
10170 {
10171 assert (o->text);
10172 if (strlen (o->text) < len)
10173 o->text = realloc (o->text, len + 1);
10174 strcpy (o->text, pair->value.s);
10175 written += len;
10176 LOG_TRACE ("MTEXT.text += %u/%u [TV 3]\n", len, written);
10177 }
10178 }
10179 /*
10180 else if (pair->code == 2 && obj->fixedtype == DWG_TYPE_LAYOUT)
10181 {
10182 Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
10183 const Dwg_DYNAPI_field *f = dwg_dynapi_entity_field
10184 ("PLOTSETTINGS", "paper_size"); dwg_dynapi_field_set_value (dwg,
10185 &o->plotsettings, f, &pair->value, 1); LOG_TRACE
10186 ("%s.plotsettings.paper_size = %s [T 2]\n", obj->name,
10187 pair->value.s); goto next_pair;
10188 }
10189 */
10190 else if (pair->code == 370 && obj->fixedtype == DWG_TYPE_LAYER)
10191 {
10192 Dwg_Object_LAYER *layer = obj->tio.object->tio.LAYER;
10193 layer->linewt = dxf_find_lweight (pair->value.i);
10194 LOG_TRACE ("LAYER.linewt = %d\n", layer->linewt);
10195 layer->flag |= layer->linewt << 5;
10196 LOG_TRACE ("LAYER.flag = 0x%x [BS 70]\n", layer->flag);
10197 goto next_pair;
10198 }
10199 else if (pair->code == 370 && obj->supertype == DWG_SUPERTYPE_ENTITY
10200 && strEQc (subclass, "AcDbEntity"))
10201 {
10202 BITCODE_RC linewt = dxf_find_lweight (pair->value.i);
10203 dwg_dynapi_common_set_value (_obj, "linewt", &linewt, 0);
10204 LOG_TRACE ("COMMON.linewt => %d [RC 370]\n", linewt);
10205 goto next_pair;
10206 }
10207 else if (pair->code == 48 && obj->supertype == DWG_SUPERTYPE_ENTITY
10208 && strEQc (subclass, "AcDbEntity"))
10209 {
10210 dwg_dynapi_common_set_value (_obj, "ltype_scale", &pair->value.d, 0);
10211 LOG_TRACE ("COMMON.ltype_scale = %f [BD 48]\n", pair->value.d);
10212 goto next_pair;
10213 }
10214 else if (pair->code == 49 && obj->fixedtype == DWG_TYPE_LTYPE)
10215 {
10216 pair = add_LTYPE_dashes (obj, dat, pair);
10217 if (pair != NULL && pair->code == 0)
10218 return pair;
10219 goto next_pair;
10220 }
10221 else if (pair->code == 71 && obj->fixedtype == DWG_TYPE_MLINESTYLE
10222 && pair->value.i != 0)
10223 {
10224 pair = add_MLINESTYLE_lines (obj, dat, pair);
10225 if (pair != NULL && pair->code == 0)
10226 return pair;
10227 goto next_pair;
10228 }
10229 else if (pair->code == 65 && obj->fixedtype == DWG_TYPE_VPORT)
10230 {
10231 Dwg_Object_VPORT *o = obj->tio.object->tio.VPORT;
10232 o->UCSVP = pair->value.i;
10233 o->UCSFOLLOW = o->VIEWMODE & 4 ? 1 : 0;
10234 o->VIEWMODE |= o->UCSVP;
10235 LOG_TRACE ("VPORT.UCSVP = %d [B 65]\n", o->UCSVP)
10236 LOG_TRACE ("VPORT.UCSFOLLOW => %d [B 0] (calc)\n", o->UCSFOLLOW)
10237 LOG_TRACE ("VPORT.VIEWMODE => %d [4BITS 71] (calc)\n",
10238 o->VIEWMODE)
10239 goto next_pair;
10240 }
10241 else if (pair->code == 90 && obj->fixedtype == DWG_TYPE_LWPOLYLINE)
10242 {
10243 pair = new_LWPOLYLINE (obj, dat, pair);
10244 if (pair != NULL && pair->code == 0)
10245 return pair;
10246 goto next_pair;
10247 }
10248 else if (pair->code == 350 && strEQc (subclass, "AcDb3dSolid")
10249 && dwg_obj_is_3dsolid (obj))
10250 {
10251 Dwg_Entity__3DSOLID *o = obj->tio.entity->tio._3DSOLID;
10252 BITCODE_H hdl = dwg_add_handleref (dwg, 5, pair->value.u, obj);
10253 LOG_TRACE ("%s.history_id = " FORMAT_REF " [H 350]\n", obj->name,
10254 ARGS_REF (hdl));
10255 o->history_id = hdl;
10256 }
10257 else if (obj->fixedtype == DWG_TYPE_MLINE)
10258 {
10259 int status = add_MLINE (obj, dat, pair, &j, &k, &l);
10260 if (status == 0)
10261 goto search_field;
10262 else if (status == 2)
10263 break;
10264 }
10265 else if (strEQc (name, "VERTEX_PFACE_FACE") && pair->code >= 71
10266 && pair->code <= 74)
10267 {
10268 Dwg_Entity_VERTEX_PFACE_FACE *o
10269 = (Dwg_Entity_VERTEX_PFACE_FACE *)_obj;
10270 j = pair->code - 71;
10271 o->vertind[j] = pair->value.i;
10272 LOG_TRACE ("VERTEX_PFACE_FACE.vertind[%d] = %d [BS %d]\n", j,
10273 pair->value.i, pair->code);
10274 }
10275 else if (obj->fixedtype == DWG_TYPE_SPLINE)
10276 {
10277 if (pair->code == 210 || pair->code == 220 || pair->code == 230)
10278 break; // ignore extrusion in the dwg (planar only)
10279 if (add_SPLINE (obj->tio.entity->tio.SPLINE, dat, pair, &j,
10280 &flag))
10281 goto next_pair;
10282 else
10283 goto search_field;
10284 }
10285 else if (obj->fixedtype == DWG_TYPE_HATCH)
10286 {
10287 if ((pair->code == 10 || pair->code == 20) && pair->value.d == 0.0)
10288 break; // elevation
10289 else if (pair->code == 91 || pair->code == 78
10290 || pair->code == 453)
10291 {
10292 pair = add_HATCH (obj, dat, pair);
10293 if (!pair || pair->code == 0) // end or unknown
10294 return pair;
10295 goto search_field;
10296 }
10297 else
10298 goto search_field;
10299 }
10300 else if (is_textlike (obj))
10301 {
10302 BITCODE_RC dataflags;
10303 if (pair->code == 10 || pair->code == 20)
10304 goto search_field;
10305 else if (pair->code == 30 && pair->value.d == 0.0)
10306 {
10307 dwg_dynapi_entity_value (_obj, obj->name, "dataflags",
10308 &dataflags, NULL);
10309 dataflags |= 1;
10310 LOG_TRACE ("%s.elevation 0.0 => dataflags = 0x%x\n",
10311 obj->name, dataflags);
10312 dwg_dynapi_entity_set_value (_obj, obj->name, "dataflags",
10313 &dataflags, 0);
10314 }
10315 else
10316 goto search_field;
10317 }
10318 else if (obj->fixedtype == DWG_TYPE_MESH)
10319 {
10320 if (pair->code == 91)
10321 {
10322 pair = add_MESH (obj, dat, pair);
10323 if (!pair || pair->code == 0) // end or unknown
10324 return pair;
10325 goto search_field;
10326 }
10327 else
10328 goto search_field;
10329 }
10330 else if (obj->fixedtype == DWG_TYPE_MLEADERSTYLE)
10331 {
10332 Dwg_Object_MLEADERSTYLE *o = obj->tio.object->tio.MLEADERSTYLE;
10333 if (pair->code == 47)
10334 o->block_scale.x = pair->value.d;
10335 else if (pair->code == 49)
10336 o->block_scale.y = pair->value.d;
10337 else if (pair->code == 140)
10338 {
10339 o->block_scale.z = pair->value.d;
10340 LOG_TRACE (
10341 "MLEADERSTYLE.block_scale = (%f, %f, %f) [3BD 47]\n",
10342 o->block_scale.x, o->block_scale.y, o->block_scale.z);
10343 }
10344 else if (pair->code == 297 && o->class_version < 2)
10345 {
10346 LOG_TRACE ("MLEADERSTYLE.text_always_left = %d [B 297] => "
10347 "class_version 2\n",
10348 pair->value.i);
10349 o->text_always_left = pair->value.i;
10350 o->class_version = 2;
10351 }
10352 else
10353 goto search_field;
10354 }
10355 else if (obj->fixedtype == DWG_TYPE_MTEXT && pair->code == 46)
10356 {
10357 Dwg_Entity_MTEXT *o = obj->tio.entity->tio.MTEXT;
10358 if (!o->num_column_heights)
10359 o->num_column_heights = 1;
10360 if (!j)
10361 {
10362 o->column_heights = (BITCODE_BD *)xcalloc (
10363 o->num_column_heights, sizeof (BITCODE_BD));
10364 if (!o->column_heights)
10365 {
10366 o->num_column_heights = 0;
10367 goto invalid_dxf;
10368 }
10369 }
10370 if (j < 0 || j >= (int)o->num_column_heights
10371 || !o->column_heights)
10372 goto invalid_dxf;
10373 assert (j < (int)o->num_column_heights);
10374 o->column_heights[j] = pair->value.d;
10375 LOG_TRACE ("MTEXT.column_heights[%d] = %f [BD* 46]\n", j,
10376 pair->value.d);
10377 }
10378 else if (obj->fixedtype == DWG_TYPE_GEODATA)
10379 {
10380 pair = add_GEODATA (obj, dat, pair);
10381 if (pair && pair->code != 0)
10382 goto search_field;
10383 else
10384 return pair;
10385 }
10386 else if (pair->code == 300 && obj->fixedtype == DWG_TYPE_CELLSTYLEMAP
10387 && strEQc (pair->value.s, "CELLSTYLE"))
10388 {
10389 Dwg_Object_CELLSTYLEMAP *o = obj->tio.object->tio.CELLSTYLEMAP;
10390 cur_cell++;
10391 if (cur_cell < 0 || cur_cell >= (int)o->num_cells)
10392 goto invalid_dxf;
10393 }
10394 else if (pair->code == 1 && pair->value.s
10395 && strEQc (pair->value.s, "TABLEFORMAT_BEGIN")
10396 && (obj->fixedtype == DWG_TYPE_CELLSTYLEMAP
10397 || obj->fixedtype == DWG_TYPE_TABLE
10398 || obj->fixedtype == DWG_TYPE_TABLESTYLE
10399 || obj->fixedtype == DWG_TYPE_TABLECONTENT))
10400 {
10401 Dwg_CellStyle *csty = NULL;
10402 Dwg_TABLESTYLE_CellStyle *tbl_sty = NULL;
10403 char key[80];
10404 if (obj->fixedtype == DWG_TYPE_CELLSTYLEMAP)
10405 {
10406 Dwg_Object_CELLSTYLEMAP *o
10407 = obj->tio.object->tio.CELLSTYLEMAP;
10408 if (cur_cell < 0 || cur_cell >= (int)o->num_cells)
10409 goto invalid_dxf;
10410 if (cur_cell == 0 && !o->cells)
10411 o->cells = (Dwg_TABLESTYLE_CellStyle *)xcalloc (
10412 o->num_cells, sizeof (Dwg_TABLESTYLE_CellStyle));
10413 tbl_sty = &o->cells[cur_cell];
10414 sprintf (key, "cells[%d]", cur_cell);
10415 csty = &tbl_sty->cellstyle;
10416 }
10417 else if (obj->fixedtype == DWG_TYPE_TABLESTYLE)
10418 {
10419 // TODO ovr
10420 Dwg_Object_TABLESTYLE *o = obj->tio.object->tio.TABLESTYLE;
10421 tbl_sty = &o->sty;
10422 csty = &o->sty.cellstyle;
10423 }
10424 if (csty)
10425 pair = add_CellStyle (obj, csty, &key[0], dat, pair);
10426 if (pair && pair->code != 0)
10427 {
10428 if (tbl_sty && pair->code == 90)
10429 {
10430 tbl_sty->id = pair->value.u;
10431 LOG_TRACE ("%s.%s.id = " FORMAT_BL " [BL %d]\n",
10432 obj->name, key, pair->value.u, pair->code);
10433 dxf_free_pair (pair);
10434 pair = dxf_read_pair (dat);
10435 }
10436 if (tbl_sty && pair && pair->code == 91)
10437 {
10438 tbl_sty->type = pair->value.u;
10439 LOG_TRACE ("%s.%s.type = " FORMAT_BL " [BL %d]\n",
10440 obj->name, key, pair->value.u, pair->code);
10441 dxf_free_pair (pair);
10442 pair = dxf_read_pair (dat);
10443 }
10444 if (tbl_sty && pair && pair->code == 300)
10445 {
10446 tbl_sty->name = dwg_add_u8_input (dwg, pair->value.s);
10447 LOG_TRACE ("%s.%s.name = \"%s\" [BL %d]\n", obj->name,
10448 key, pair->value.s, pair->code);
10449 dxf_free_pair (pair);
10450 pair = dxf_read_pair (dat);
10451 }
10452 if (tbl_sty && pair && pair->code == 309
10453 && strEQc (pair->value.s, "CELLSTYLE_END"))
10454 goto next_pair;
10455 else
10456 goto search_field;
10457 }
10458 else
10459 return pair;
10460 }
10461 else if (obj->fixedtype == DWG_TYPE_VPORT && pair->code == 41)
10462 {
10463 Dwg_Object_VPORT *o = obj->tio.object->tio.VPORT;
10464 o->aspect_ratio = pair->value.d;
10465 o->view_width = o->aspect_ratio * o->VIEWSIZE;
10466 LOG_TRACE ("VPORT.aspect_ratio = %f [BD 41]\n", o->aspect_ratio);
10467 LOG_TRACE ("VPORT.view_width = %f [BD 0]\n", o->view_width);
10468 }
10469 else if (strEQc (subclass, "AcDbShHistoryNode"))
10470 {
10471 // add_AcDbShHistoryNode (obj, _obj)
10472 Dwg_ACSH_HistoryNode *hn;
10473 const Dwg_DYNAPI_field *f1
10474 = dwg_dynapi_entity_field (obj->name, "history_node");
10475 if (!f1)
10476 goto search_field;
10477 hn = (Dwg_ACSH_HistoryNode *)&((char *)_obj)[f1->offset];
10478 if (pair->code == 90)
10479 {
10480 hn->major = pair->value.u;
10481 LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", name, "history_node",
10482 "major", pair->value.u, pair->code);
10483 }
10484 else if (pair->code == 91)
10485 {
10486 hn->minor = pair->value.u;
10487 LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", name, "history_node",
10488 "minor", pair->value.u, pair->code);
10489 }
10490 else if (pair->code == 92)
10491 {
10492 hn->step_id = pair->value.u;
10493 LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", name, "history_node",
10494 "step_id", pair->value.u, pair->code);
10495 }
10496 else if (pair->code == 62)
10497 {
10498 hn_color:
10499 hn->color.index = pair->value.l;
10500 LOG_TRACE ("%s.%s.%s.index = %u [CMC %d]\n", name,
10501 "history_node", "color", pair->value.u,
10502 pair->code);
10503 }
10504 else if (pair->code == 347)
10505 {
10506 hn->material
10507 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
10508 LOG_TRACE ("%s.%s.%s = " FORMAT_REF " [H %d]\n", name,
10509 "history_node", "material",
10510 ARGS_REF (hn->material), pair->code);
10511 }
10512 else if (hn && pair->code == 40) // VECTOR_N1
10513 {
10514 hn->trans = (BITCODE_BD *)xcalloc (16, sizeof (BITCODE_BD));
10515 if (!hn->trans)
10516 return NULL;
10517 // BD* starting at 40-55
10518 for (j = 0; j < 16; j++)
10519 {
10520 hn->trans[j] = pair->value.d;
10521 LOG_TRACE ("%s.history_node.trans[%d] = %f [BD %d]\n",
10522 obj->name, j, pair->value.d, j + 40);
10523 dxf_free_pair (pair);
10524 pair = dxf_read_pair (dat);
10525 if (!pair || pair->code == 0)
10526 return pair;
10527 if (pair->code == 62)
10528 goto hn_color;
10529 if (pair->code != j + 41)
10530 goto search_field;
10531 }
10532 }
10533 }
10534 else if (dwg_obj_is_acsh (obj) && memBEGINc (subclass, "AcDbSh")
10535 && (pair->code == 90 || pair->code == 91))
10536 {
10537 const char *_key = pair->code == 90 ? "major" : "minor";
10538 const Dwg_DYNAPI_field *f1
10539 = dwg_dynapi_entity_field (obj->name, _key);
10540 if (!f1)
10541 goto search_field;
10542 dwg_dynapi_field_set_value (dwg, _obj, f1, &pair->value, 0);
10543 LOG_TRACE ("%s.%s = %u [BL %d]\n", name, _key, pair->value.u,
10544 pair->code);
10545 }
10546 else if (strEQc (subclass, "AcDbEvalExpr"))
10547 {
10548 pair = add_AcDbEvalExpr (obj, (char *)_obj, dat, pair);
10549 if (pair && pair->code == 100) // success
10550 goto start_loop;
10551 else
10552 goto search_field;
10553 }
10554 else if (obj->fixedtype == DWG_TYPE_LEADER
10555 && (pair->code == 10 || pair->code == 20
10556 || pair->code == 30))
10557 {
10558 Dwg_Entity_LEADER *o = obj->tio.entity->tio.LEADER;
10559 if (!j && pair->code == 10)
10560 {
10561 o->points = (BITCODE_3BD *)xcalloc (o->num_points,
10562 sizeof (BITCODE_3BD));
10563 if (!o->points)
10564 {
10565 o->num_points = 0;
10566 goto invalid_dxf;
10567 }
10568 }
10569 if (j < 0 || j >= (int)o->num_points || !o->points)
10570 goto invalid_dxf;
10571 assert (j >= 0);
10572 assert (j < (int)o->num_points);
10573 assert (o->points);
10574
10575 if (pair->code == 10)
10576 o->points[j].x = pair->value.d;
10577 else if (pair->code == 20)
10578 o->points[j].y = pair->value.d;
10579 else if (pair->code == 30)
10580 {
10581 o->points[j].z = pair->value.d;
10582 LOG_TRACE ("LEADER.points[%d] = (%f, %f, %f) [3BD* 10]\n", j,
10583 o->points[j].x, o->points[j].y, o->points[j].z);
10584 j++;
10585 }
10586 }
10587 else if (pair->code == 71
10588 && strEQc (subclass, "AcDbSectionViewStyle"))
10589 {
10590 pair = add_AcDbSectionViewStyle (obj, dat);
10591 if (!pair) // success
10592 goto start_loop;
10593 else
10594 goto search_field;
10595 }
10596 else if (pair->code == 71
10597 && strEQc (subclass, "AcDbDetailViewStyle")
10598 && obj->fixedtype == DWG_TYPE_DETAILVIEWSTYLE)
10599 {
10600 pair = add_AcDbDetailViewStyle (obj, dat);
10601 if (pair && pair->code == 100) // success
10602 goto start_loop;
10603 else
10604 goto search_field;
10605 }
10606 else if (pair->code == 300 && strEQc (subclass, "AcDbBlockElement"))
10607 {
10608 pair = add_AcDbBlockElement (obj, (char *)_obj, dat, pair);
10609 if (!pair) // success
10610 goto start_loop;
10611 else
10612 goto search_field;
10613 }
10614 else if (pair->code == 91 && strEQc (subclass, "AcDbBlockgrip"))
10615 {
10616 pair = add_AcDbBlockGrip (obj, (char *)_obj, dat, pair);
10617 if (!pair) // success
10618 goto start_loop;
10619 else
10620 goto search_field;
10621 }
10622 else if (pair->code == 93 && strEQc (subclass, "AcDbBlockVisibilityParameter"))
10623 {
10624 pair = add_AcDbBlockVisibilityParameter (
10625 obj, (Dwg_Object_BLOCKVISIBILITYPARAMETER *)_obj, dat, pair);
10626 if (!pair) // success
10627 goto start_loop;
10628 else
10629 goto search_field;
10630 }
10631 else if (pair->code == 307
10632 && strEQc (subclass, "AcDbBlockLinearConstraintParameter"))
10633 {
10634 Dwg_BLOCKPARAMVALUESET *value_set
10635 = &((Dwg_Object_BLOCKALIGNEDCONSTRAINTPARAMETER *)_obj)
10636 ->value_set;
10637 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10638 if (!pair) // success
10639 goto start_loop;
10640 else
10641 goto search_field;
10642 }
10643 else if (pair->code == 307 && strEQc (obj->name, "BLOCKLINEARPARAMETER"))
10644 {
10645 Dwg_BLOCKPARAMVALUESET *value_set
10646 = &((Dwg_Object_BLOCKLINEARPARAMETER *)_obj)
10647 ->value_set;
10648 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10649 if (!pair) // success
10650 goto start_loop;
10651 else
10652 goto search_field;
10653 }
10654 else if (pair->code == 307 && strEQc (obj->name, "BLOCKROTATIONPARAMETER"))
10655 {
10656 Dwg_BLOCKPARAMVALUESET *value_set
10657 = &((Dwg_Object_BLOCKROTATIONPARAMETER *)_obj)
10658 ->angle_value_set;
10659 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10660 if (!pair) // success
10661 goto start_loop;
10662 else
10663 goto search_field;
10664 }
10665 else if (pair->code == 307 && strEQc (obj->name, "BLOCKANGULARCONSTRAINTPARAMETER"))
10666 {
10667 Dwg_BLOCKPARAMVALUESET *value_set
10668 = &((Dwg_Object_BLOCKANGULARCONSTRAINTPARAMETER *)_obj)
10669 ->value_set;
10670 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10671 if (!pair) // success
10672 goto start_loop;
10673 else
10674 goto search_field;
10675 }
10676 else if (pair->code == 307 && strEQc (obj->name, "BLOCKDIAMETRICCONSTRAINTPARAMETER"))
10677 {
10678 Dwg_BLOCKPARAMVALUESET *value_set
10679 = &((Dwg_Object_BLOCKDIAMETRICCONSTRAINTPARAMETER *)_obj)
10680 ->value_set;
10681 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10682 if (!pair) // success
10683 goto start_loop;
10684 else
10685 goto search_field;
10686 }
10687 else if (pair->code == 307 && strEQc (obj->name, "BLOCKRADIALCONSTRAINTPARAMETER"))
10688 {
10689 Dwg_BLOCKPARAMVALUESET *value_set
10690 = &((Dwg_Object_BLOCKRADIALCONSTRAINTPARAMETER *)_obj)
10691 ->value_set;
10692 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10693 if (!pair) // success
10694 goto start_loop;
10695 else
10696 goto search_field;
10697 }
10698 else if (pair->code == 309 && strEQc (obj->name, "BLOCKXYPARAMETER"))
10699 {
10700 Dwg_BLOCKPARAMVALUESET *value_set
10701 = &((Dwg_Object_BLOCKXYPARAMETER *)_obj)
10702 ->y_value_set;
10703 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10704 if (!pair) // success
10705 goto start_loop;
10706 else
10707 goto search_field;
10708 }
10709 else if (pair->code == 309 && strEQc (obj->name, "BLOCKPOLARPARAMETER"))
10710 {
10711 Dwg_BLOCKPARAMVALUESET *value_set
10712 = &((Dwg_Object_BLOCKPOLARPARAMETER *)_obj)
10713 ->distance_value_set;
10714 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10715 if (!pair) // success
10716 goto start_loop;
10717 else
10718 goto search_field;
10719 }
10720 else if (pair->code == 410 && strEQc (obj->name, "BLOCKXYPARAMETER"))
10721 {
10722 Dwg_BLOCKPARAMVALUESET *value_set
10723 = &((Dwg_Object_BLOCKXYPARAMETER *)_obj)
10724 ->x_value_set;
10725 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10726 if (!pair) // success
10727 goto start_loop;
10728 else
10729 goto search_field;
10730 }
10731 else if (pair->code == 410 && strEQc (obj->name, "BLOCKPOLARPARAMETER"))
10732 {
10733 Dwg_BLOCKPARAMVALUESET *value_set
10734 = &((Dwg_Object_BLOCKPOLARPARAMETER *)_obj)
10735 ->angle_value_set;
10736 pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10737 if (!pair) // success
10738 goto start_loop;
10739 else
10740 goto search_field;
10741 }
10742 else if (pair->code == 8 && obj->fixedtype == DWG_TYPE_LAYERFILTER
10743 && strEQc (subclass, "AcDbLayerFilter"))
10744 {
10745 // num_names
10746 Dwg_Object_LAYERFILTER *o = obj->tio.object->tio.LAYERFILTER;
10747 if (!o->names)
10748 {
10749 o->names = (BITCODE_T *)xcalloc (1, sizeof (BITCODE_T));
10750 j = 0;
10751 }
10752 else
10753 o->names = (BITCODE_T *)realloc (
10754 o->names, (o->num_names + 1) * sizeof (BITCODE_T));
10755 if (!o->names || j < 0 || j >= (int)o->num_names)
10756 goto invalid_dxf;
10757 assert (j >= 0 && j < (int)o->num_names && o->names);
10758 o->names[j] = dwg_add_u8_input (dwg, pair->value.s);
10759 LOG_TRACE ("%s.%s[%d] = %s [%s %d]\n", name, "names", j,
10760 pair->value.s, "T", pair->code);
10761 j++;
10762 o->num_names = j;
10763 goto next_pair;
10764 }
10765 else
10766 search_field:
10767 { // search all specific fields and common fields for the DXF
10768 const Dwg_DYNAPI_field *f;
10769 const Dwg_DYNAPI_field *fields
10770 = dwg_dynapi_entity_fields (obj->name);
10771 if (!pair || pair->code == 0)
10772 break;
10773 if (!fields)
10774 {
10775 LOG_ERROR ("Illegal object name %s, no dynapi fields",
10776 obj->name);
10777 break;
10778 }
10779 for (f = &fields[0]; f->name; f++)
10780 {
10781 LOG_INSANE ("-%s.%s [%d %s] vs %d\n", obj->name, f->name,
10782 f->dxf, f->type, pair->code)
10783 // VECTORs. need to be malloced, and treated specially
10784 if (pair->code != 3 && f->is_malloc && !f->is_string
10785 && strNE (f->name, "parent")) // parent set in NEW_OBJECT
10786 {
10787 const Dwg_DYNAPI_field *num_f;
10788 // FIELD_2RD_VECTOR (clip_verts, num_clip_verts, 11|14);
10789 if (pair->code >= 10 && pair->code <= 24
10790 && strEQc (f->name, "clip_verts")) // 11 or 14
10791 {
10792 BITCODE_BL num_clip_verts = 0;
10793 BITCODE_2RD *clip_verts;
10794 // 11 has no num_clip_verts: realloc. clip_inverts
10795 // has.
10796 if (pair->code == 14 || pair->code == 24)
10797 {
10798 dwg_dynapi_entity_value (_obj, obj->name,
10799 "num_clip_verts",
10800 &num_clip_verts, NULL);
10801 LOG_INSANE ("%s.num_clip_verts = %d, j = %d\n",
10802 name, num_clip_verts, j);
10803 }
10804 dwg_dynapi_entity_value (_obj, obj->name,
10805 "clip_verts", &clip_verts,
10806 NULL);
10807 // assert (j == 0 || j < (int)num_clip_verts);
10808 if (pair->code < 20)
10809 {
10810 // no need to realloc
10811 if (!j && pair->code == 14)
10812 {
10813 clip_verts = (BITCODE_2RD *)xcalloc (
10814 num_clip_verts, sizeof (BITCODE_2RD));
10815 dwg_dynapi_entity_set_value (_obj, obj->name,
10816 f->name,
10817 &clip_verts, 0);
10818 }
10819 else if (pair->code == 11)
10820 {
10821 clip_verts = (BITCODE_2RD *)realloc (
10822 clip_verts,
10823 (j + 1) * sizeof (BITCODE_2RD));
10824 memset (&clip_verts[j], 0,
10825 sizeof (BITCODE_2RD));
10826 dwg_dynapi_entity_set_value (_obj, obj->name,
10827 f->name,
10828 &clip_verts, 0);
10829 }
10830 if (j >= 0 && j < (int)num_clip_verts
10831 && clip_verts)
10832 clip_verts[j].x = pair->value.d;
10833 }
10834 else if (pair->code < 30)
10835 {
10836 if (j >= 0 && j < (int)num_clip_verts
10837 && clip_verts)
10838 {
10839 clip_verts[j].y = pair->value.d;
10840 LOG_TRACE (
10841 "%s.%s[%d] = (%f, %f) [2RD* %d]\n", name,
10842 "clip_verts", j, clip_verts[j].x,
10843 clip_verts[j].y, pair->code - 10);
10844 j++;
10845 }
10846 if (pair->code == 21)
10847 {
10848 dwg_dynapi_entity_set_value (
10849 _obj, obj->name, "num_clip_verts", &j,
10850 0);
10851 LOG_TRACE ("%s.num_clip_verts = %d\n", name,
10852 j);
10853 }
10854 }
10855 goto next_pair;
10856 }
10857 // point vectors with known num_field
10858 else if ((*f->type == '2' || *f->type == '3')
10859 && (f->type[2] == 'D'
10860 || strEQc (&f->type[1], "DPOINT*"))
10861 && (num_f = find_numfield (fields, f->name)))
10862 {
10863 // how many points
10864 long size = get_numfield_value (_obj, num_f);
10865 double *pts;
10866 int is2d = *f->type == '2';
10867 if (!size)
10868 {
10869 LOG_TRACE ("Ignore empty %s.%s VECTOR [%s %d]\n",
10870 name, f->name, f->type, pair->code);
10871 goto next_pair;
10872 }
10873 else if (j == 0 && pair->code < 20)
10874 {
10875 pts = (double *)xcalloc (size, is2d ? 16 : 24);
10876 if (!pts)
10877 return NULL;
10878 LOG_TRACE ("%s.%s size: %ld\n", name, f->name,
10879 size);
10880 pts[0] = pair->value.d;
10881 dwg_dynapi_entity_set_value (_obj, obj->name,
10882 f->name, &pts, 0);
10883 }
10884 else if (j > 0 && j < size)
10885 {
10886 int _i = is2d ? j * 2 : j * 3;
10887 dwg_dynapi_entity_value (_obj, obj->name,
10888 f->name, &pts, NULL);
10889 if (pair->code < 20 && pts != NULL)
10890 {
10891 pts[_i] = pair->value.d;
10892 }
10893 else if (pair->code < 30 && pts != NULL)
10894 {
10895 if (is2d)
10896 LOG_TRACE (
10897 "%s.%s[%d] = (%f, %f) [%s %d]\n", name,
10898 f->name, j, pts[_i], pair->value.d,
10899 f->type, pair->code);
10900 pts[_i + 1] = pair->value.d;
10901 }
10902 else if (*f->type == '3' && pts)
10903 {
10904 LOG_TRACE (
10905 "%s.%s[%d] = (%f, %f, %f) [%s %d]\n",
10906 name, f->name, j, pts[_i], pts[_i + 1],
10907 pair->value.d, f->type, pair->code);
10908 pts[_i + 2] = pair->value.d;
10909 if (j == size - 1)
10910 j = 0; // restart
10911 }
10912 }
10913 else if (j > size)
10914 LOG_ERROR ("%s.%s overflow %d > %ld", name,
10915 num_f->name, j, size)
10916 }
10917 else if (f->dxf == pair->code)
10918 {
10919 LOG_WARN ("Ignore %s.%s VECTOR [%s %d]", name,
10920 f->name, f->type, pair->code);
10921 goto next_pair;
10922 }
10923 }
10924 else if (obj->fixedtype == DWG_TYPE_VISUALSTYLE
10925 && dwg->header.from_version >= R_2010 && pair->code == 176
10926 && prev_vstyle)
10927 {
10928 // which 176 of the many? the one after the previous
10929 // field
10930 char fieldname[40];
10931 strcpy (fieldname, prev_vstyle->name);
10932 strcat (fieldname, "_int");
10933 f = prev_vstyle + 1;
10934 if (strEQc (fieldname, "display_brightness_bl_int"))
10935 {
10936 strcpy (fieldname, "display_brightness_int");
10937 f++;
10938 }
10939 if (strEQ (fieldname, f->name))
10940 {
10941 LOG_HANDLE ("found %s.%s:\n", name, fieldname);
10942 if (strEQc (f->name, "display_shadow_type_int")
10943 && dwg->header.from_version >= R_2013)
10944 {
10945 Dwg_Object_VISUALSTYLE *o = obj->tio.object->tio.VISUALSTYLE;
10946 o->display_shadow_type_int = pair->value.i;
10947 pair = add_VISUALSTYLE_props (obj, dat);
10948 if (!pair) // success
10949 goto start_loop;
10950 else // or better advance to the next 0
10951 goto search_field;
10952 }
10953 else
10954 goto matching_pair;
10955 }
10956 else
10957 LOG_WARN ("%s.%s [BS 176] not found in dynapi", name,
10958 fieldname);
10959 }
10960 else if (f->dxf == pair->code) // matching DXF code
10961 {
10962 matching_pair:
10963 if (obj->fixedtype == DWG_TYPE_VISUALSTYLE
10964 && dwg->header.from_version >= R_2010 && pair->code != 176)
10965 {
10966 prev_vstyle = f;
10967 }
10968 // exceptions, where there's another field 92:
10969 if (pair->code == 92 && is_entity
10970 && dwg->header.from_version < R_2010
10971 && strEQc (subclass, "AcDbEntity"))
10972 // not MULTILEADER.text_color, nor MESH.num_vertex
10973 {
10974 pair = add_ent_preview (obj, dat, pair);
10975 goto start_loop;
10976 }
10977 else if (pair->code == 3 && pair->value.s
10978 && memBEGINc (obj->name, "DICTIONARY")
10979 && strNE (obj->name, "DICTIONARYVAR"))
10980 {
10981 strncpy (text, pair->value.s, 254);
10982 text[255] = '\0';
10983 goto next_pair; // skip setting texts TV*
10984 }
10985 // convert angle to radians
10986 else if (pair->code >= 50 && pair->code <= 55)
10987 {
10988 BITCODE_BD ang;
10989 if (pair->value.d == 0.0)
10990 goto next_pair;
10991 ang = deg2rad (pair->value.d);
10992 dwg_dynapi_entity_set_value (_obj, obj->name,
10993 f->name, &ang, 0);
10994 LOG_TRACE ("%s.%s = %f (from DEG %f°) [%s %d]\n",
10995 name, f->name, ang, pair->value.d,
10996 f->type, pair->code);
10997 goto next_pair; // found
10998 }
10999 // convert double to text (e.g. ATEXT)
11000 else if (strEQc (f->type, "D2T")
11001 && pair->type == DWG_VT_REAL)
11002 {
11003 // TODO: for now we need to do double-conversion
11004 // (str->dbl->str), because we don't have the initial
11005 // dat->byte position.
11006 char *d2t = (char *)xcalloc (36, 1);
11007 sprintf (d2t, "%f", pair->value.d);
11008 dwg_dynapi_entity_set_value (_obj, obj->name,
11009 f->name, &d2t, 1);
11010 LOG_TRACE ("%s.%s = %s (from %f°) [%s %d]\n", name,
11011 f->name, d2t, pair->value.d, f->type,
11012 pair->code);
11013 free (d2t);
11014 goto next_pair; // found
11015 }
11016 // resolve handle, by name or ref
11017 else if (strEQc (f->type, "H"))
11018 {
11019 BITCODE_H ref = find_tablehandle (dwg, pair);
11020 if (!ref)
11021 {
11022 if (pair->code > 300)
11023 {
11024 int code = 5; // default: soft pointer
11025 if (obj->fixedtype == DWG_TYPE_VIEWPORT)
11026 {
11027 switch (pair->code)
11028 {
11029 case 340:
11030 case 332:
11031 case 333:
11032 code = 4;
11033 break;
11034 case 361:
11035 code = 3;
11036 break;
11037 default:
11038 break;
11039 }
11040 }
11041 else if (strEQc (f->name, "history_id"))
11042 code = 4;
11043 else if (strEQc (f->name, "background"))
11044 code = 4;
11045 else if (strEQc (f->name, "dimensionobj"))
11046 code = 4;
11047 else if (strEQc (f->name, "active_viewport")
11048 || strEQc (f->name, "host_block"))
11049 code = 4;
11050 else if (strEQc (f->name, "writedep")
11051 || strEQc (f->name, "readdep"))
11052 code = 4;
11053 else if (strEQc (f->name, "imagedefreactor"))
11054 code = 3;
11055 else if (strEQc (f->name, "table_style"))
11056 code = 3;
11057 ref = dwg_add_handleref (dwg, code,
11058 pair->value.u, obj);
11059 LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n",
11060 name, f->name, ARGS_REF (ref),
11061 pair->code);
11062 }
11063 else if (pair->type == DWG_VT_INT32 && pair->value.u)
11064 {
11065 ref = dwg_add_handleref (dwg, 5,
11066 pair->value.u, obj);
11067 LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n",
11068 name, f->name, ARGS_REF (ref),
11069 pair->code);
11070 }
11071 else if ((pair->type == DWG_VT_STRING
11072 || pair->type == DWG_VT_HANDLE)
11073 && pair->value.s)
11074 {
11075 obj_hdls = array_push (
11076 obj_hdls, f->name, pair->value.s,
11077 obj->tio.object->objid);
11078 LOG_TRACE ("%s.%s: name %s -> H for code "
11079 "%d later\n",
11080 name, f->name, pair->value.s,
11081 pair->code);
11082 }
11083 }
11084 else
11085 {
11086 dwg_dynapi_entity_set_value (_obj, obj->name,
11087 f->name, &ref, 1);
11088 LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n",
11089 name, f->name, ARGS_REF (ref),
11090 pair->code);
11091 }
11092 goto next_pair; // found
11093 }
11094 // only 2D or 3D points .x
11095 else if (f->size > 8
11096 && (strchr (f->type, '2')
11097 || strchr (f->type, '3')
11098 || strEQc (f->type, "BE")))
11099 {
11100 // pt.x = 0.0;
11101 // if (pair->value.d == 0.0) // ignore defaults
11102 // goto next_pair;
11103 pt.x = pair->value.d;
11104 dwg_dynapi_entity_set_value (_obj, obj->name,
11105 f->name, &pt, 1);
11106 LOG_TRACE ("%s.%s.x = %f [%s %d]\n", name, f->name,
11107 pair->value.d, f->type, pair->code);
11108 goto next_pair; // found
11109 }
11110 else if (pair->type == DWG_VT_REAL
11111 && strEQc (f->type, "TIMEBLL"))
11112 {
11113 static BITCODE_TIMEBLL date = { 0, 0, 0 };
11114 date.value = pair->value.d;
11115 date.days = (BITCODE_BL)trunc (pair->value.d);
11116 date.ms = (BITCODE_BL) (86400000.0
11117 * (date.value - date.days));
11118 LOG_TRACE ("%s.%s %.09f (" FORMAT_BL ", " FORMAT_BL
11119 ") [TIMEBLL %d]\n",
11120 name, f->name, date.value, date.days,
11121 date.ms, pair->code);
11122 dwg_dynapi_entity_set_value (_obj, obj->name,
11123 f->name, &date, 1);
11124 goto next_pair;
11125 }
11126 else if (f->size > 8 && strEQc (f->type, "CMC"))
11127 {
11128 BITCODE_CMC color;
11129 dwg_dynapi_entity_value (_obj, obj->name, f->name,
11130 &color, NULL);
11131 if (pair->code < 90)
11132 {
11133 color.index = pair->value.i;
11134 if (pair->value.i == 256)
11135 color.method = 0xc2;
11136 else if (pair->value.i == 257)
11137 color.method = 0xc8;
11138 else if (pair->value.i < 256 && dat->from_version >= R_2004)
11139 {
11140 color.method = 0xc3;
11141 color.rgb = 0xc3000000 | color.index;
11142 color.index = 256;
11143 }
11144 LOG_TRACE ("%s.%s.index = %d [%s %d]\n", name,
11145 f->name, color.index, "CMC",
11146 pair->code);
11147 if (color.rgb)
11148 LOG_TRACE ("%s.%s.rgb = 0x%08x [%s %d]\n", name,
11149 f->name, color.rgb, "CMC",
11150 pair->code);
11151 }
11152 else if (pair->code < 430)
11153 {
11154 color.rgb = pair->value.l;
11155 color.method = pair->value.l >> 0x18;
11156 if (pair->value.l == 257)
11157 {
11158 color.method = 0xc8;
11159 color.rgb = 0xc8000000;
11160 }
11161 // color.alpha = (pair->value.l & 0xFF000000) >>
11162 // 24; if (color.alpha)
11163 // color.alpha_type = 3;
11164 LOG_TRACE ("%s.%s.rgb = %08X [%s %d]\n", name,
11165 f->name, pair->value.u, "CMC",
11166 pair->code);
11167 }
11168 else if (pair->code < 440)
11169 {
11170 color.flag |= 0x10;
11171 color.name = dwg_add_u8_input (dwg, pair->value.s);
11172 LOG_TRACE ("%s.%s.name = %s [%s %d]\n", name,
11173 f->name, pair->value.s, "CMC",
11174 pair->code);
11175 }
11176 else if (pair->code < 450)
11177 {
11178 color.alpha = (pair->value.l & 0xFF000000) >> 24;
11179 if (color.alpha)
11180 color.alpha_type = 3;
11181 LOG_TRACE ("%s.%s.alpha = %08X [%s %d]\n", name,
11182 f->name, pair->value.u, "CMC",
11183 pair->code);
11184 }
11185 dwg_dynapi_entity_set_value (_obj, obj->name,
11186 f->name, &color, 1);
11187 goto next_pair; // found, early exit
11188 }
11189 else
11190 dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11191 &pair->value, 1);
11192 if (f->is_string)
11193 {
11194 LOG_TRACE ("%s.%s = %s [%s %d]\n", name, f->name,
11195 pair->value.s, f->type, pair->code);
11196 }
11197 else if (strchr (&f->type[1], 'D'))
11198 {
11199 LOG_TRACE ("%s.%s = %f [%s %d]\n", name, f->name,
11200 pair->value.d, f->type, pair->code);
11201 }
11202 else
11203 {
11204 LOG_TRACE ("%s.%s = %ld [%s %d]\n", name, f->name,
11205 pair->value.l, f->type, pair->code);
11206 }
11207 j = 0; // not a point nor vector member, so reset
11208 goto next_pair; // found, early exit
11209 }
11210 // wrong code, maybe a point .y or .z
11211 else if ((*f->type == '3' || *f->type == '2'
11212 || strEQc (f->type, "BE"))
11213 && (strstr (f->type, "_1")
11214 ? f->dxf + 1 == pair->code // 2BD_1
11215 : f->dxf + 10 == pair->code))
11216 {
11217 // pt.y = 0.0;
11218 // if (pair->value.d == 0.0) // ignore defaults
11219 // goto next_pair;
11220 dwg_dynapi_entity_value (_obj, obj->name, f->name, &pt,
11221 NULL);
11222 pt.y = pair->value.d;
11223 dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11224 &pt, 1);
11225 LOG_TRACE ("%s.%s.y = %f [%s %d]\n", name, f->name,
11226 pair->value.d, f->type, pair->code);
11227 goto next_pair; // found, early exit
11228 }
11229 else if ((*f->type == '3' || *f->type == '2'
11230 || strEQc (f->type, "BE"))
11231 && (strstr (f->type, "_1")
11232 ? f->dxf + 2 == pair->code // 2BD_1
11233 : f->dxf + 20 == pair->code))
11234 {
11235 pt.z = 0.0;
11236 // can ignore z or 0.0? e.g. no VPORT.view_target
11237 if (strNE (name, "_3DFACE") && strNE (f->name, "scale")
11238 && *f->type == '2')
11239 goto next_pair;
11240 dwg_dynapi_entity_value (_obj, obj->name, f->name, &pt,
11241 NULL);
11242 pt.z = pair->value.d;
11243 dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11244 &pt, 0);
11245 LOG_TRACE ("%s.%s.z = %f [%s %d]\n", name, f->name,
11246 pair->value.d, f->type, pair->code);
11247
11248 // 3DD scale
11249 if (strEQc (f->name, "scale")
11250 && dwg->header.version >= R_2000
11251 && dwg_dynapi_entity_field (obj->name, "scale_flag")
11252 && dwg_dynapi_entity_value (_obj, obj->name,
11253 "scale_flag",
11254 &scale_flag, NULL))
11255 { // set scale_flag
11256 scale_flag = 0;
11257 if (pt.x == 1.0 && pt.y == 1.0 && pt.z == 1.0)
11258 scale_flag = 3;
11259 else if (pt.x == 1.0)
11260 scale_flag = 1;
11261 else if (pt.x == pt.y && pt.x == pt.z)
11262 scale_flag = 2;
11263 dwg_dynapi_entity_set_value (
11264 _obj, obj->name, "scale_flag", &scale_flag, 0);
11265 LOG_TRACE ("%s.scale_flag = %d [BB 0]\n", name,
11266 scale_flag);
11267 }
11268 // 3DFACE.z_is_zero
11269 else if (strEQc (name, "_3DFACE")
11270 && strEQc (f->name, "corner1")
11271 && dwg->header.version >= R_2000 && pt.z == 0.0)
11272 {
11273 BITCODE_B z_is_zero = 1;
11274 dwg_dynapi_entity_set_value (
11275 _obj, obj->name, "z_is_zero", &z_is_zero, 0);
11276 LOG_TRACE ("%s.z_is_zero = 1 [B 0]\n", name);
11277 }
11278
11279 goto next_pair; // found, early exit
11280 }
11281 // FIELD_VECTOR_N BITCODE_BD transmatrix[16]:
11282 else if (strEQc (f->type, "BD*")
11283 && (strEQc (name, "EXTRUDEDSURFACE")
11284 || strEQc (name, "LOFTEDSURFACE")
11285 || strEQc (name, "SWEPTSURFACE")
11286 || strEQc (name, "REVOLVEDSURFACE")
11287 || strEQc (name, "MATERIAL")
11288 || strEQc (name, "SPATIAL_FILTER")
11289 || /* max 12 */
11290 strEQc (name, "ACSH_SWEEP_CLASS"))
11291 && ((pair->code >= 40 && pair->code <= 49)
11292 || (pair->code <= 142 && pair->code <= 147)))
11293 {
11294 // 16x BD, via j
11295 BITCODE_BD *matrix;
11296 dwg_dynapi_entity_value (_obj, obj->name, f->name,
11297 &matrix, NULL);
11298 if (!matrix)
11299 {
11300 matrix = (BITCODE_BD *)xcalloc (16,
11301 sizeof (BITCODE_BD));
11302 if (!matrix)
11303 goto invalid_dxf;
11304 j = 0;
11305 }
11306 if (j < 0 || j >= 16 || !matrix)
11307 goto invalid_dxf;
11308 assert (j >= 0 && j < 16 && matrix);
11309 matrix[j] = pair->value.d;
11310 dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11311 &matrix, 0);
11312 LOG_TRACE ("%s.%s[%d] = %f [%s %d]\n", name, f->name, j,
11313 pair->value.d, f->type, pair->code);
11314 j++;
11315 goto next_pair;
11316 }
11317 }
11318 LOG_INSANE ("----\n");
11319 if (*subclass) // embedded subclasses/objects
11320 {
11321 if (obj->fixedtype == DWG_TYPE_LAYOUT
11322 && strEQc (subclass, "AcDbPlotSettings"))
11323 {
11324 Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
11325 int unique;
11326 static double pt_x;
11327 static const Dwg_DYNAPI_field *pt_f = NULL;
11328 if (pair->code == 6 && *pair->value.s)
11329 {
11330 if (dwg->header.version < R_2004)
11331 {
11332 f = dwg_dynapi_entity_field ("PLOTSETTINGS",
11333 "plotview_name");
11334 dwg_dynapi_field_set_value (
11335 dwg, &o->plotsettings, f, &pair->value, 1);
11336 }
11337 else
11338 {
11339 BITCODE_H ref = find_tablehandle (dwg, pair);
11340 f = dwg_dynapi_entity_field ("PLOTSETTINGS",
11341 "plotview");
11342 dwg_dynapi_field_set_value (
11343 dwg, &o->plotsettings, f, &ref, 1);
11344 }
11345 goto next_pair;
11346 }
11347 fields = dwg_dynapi_entity_fields ("PLOTSETTINGS");
11348 f = dwg_dynapi_field_dxf (fields, pair->code, &unique);
11349 if (f && unique)
11350 {
11351 if (*f->type == '2') // 2D points
11352 {
11353 pt_f = f;
11354 pt_x = pair->value.d;
11355 goto next_pair;
11356 }
11357 else if (strEQc (f->type, "H"))
11358 {
11359 BITCODE_H ref = find_tablehandle (dwg, pair);
11360 if (!ref)
11361 {
11362 if (pair->code > 300)
11363 {
11364 int code = 4;
11365 ref = dwg_add_handleref (
11366 dwg, code, pair->value.u, obj);
11367 LOG_TRACE (
11368 "%s.plotsettings.%s = " FORMAT_REF
11369 " [H %d]\n",
11370 name, f->name, ARGS_REF (ref),
11371 pair->code);
11372 }
11373 goto next_pair; // found
11374 }
11375 else
11376 {
11377 dwg_dynapi_field_set_value (
11378 dwg, &o->plotsettings, f, &ref, 1);
11379 LOG_TRACE (
11380 "set %s.plotsettings.%s " FORMAT_REF
11381 " [H %d]\n",
11382 obj->name, f->name, ARGS_REF (ref),
11383 pair->code);
11384 goto next_pair; // found
11385 }
11386 }
11387 else
11388 {
11389 LOG_TRACE ("set %s.plotsettings.%s [%s %d]\n",
11390 obj->name, f->name, f->type,
11391 pair->code);
11392 dwg_dynapi_field_set_value (
11393 dwg, &o->plotsettings, f, &pair->value, 1);
11394 goto next_pair;
11395 }
11396 }
11397 else if (pt_f
11398 && (pair->code == 47 || pair->code == 49
11399 || pair->code == 141 || pair->code == 149))
11400 {
11401 BITCODE_2BD pt2;
11402 pt2.x = pt_x;
11403 pt2.y = pair->value.d;
11404 LOG_TRACE ("set %s.plotsettings.%s [%s %d]\n",
11405 obj->name, pt_f->name, pt_f->type,
11406 pt_f->dxf);
11407 dwg_dynapi_field_set_value (dwg, &o->plotsettings,
11408 pt_f, &pt2, 1);
11409 goto next_pair;
11410 }
11411 else
11412 LOG_WARN ("Unknown DXF code %d for %s", pair->code,
11413 subclass);
11414 }
11415 }
11416 fields = is_entity ? dwg_dynapi_common_entity_fields ()
11417 : dwg_dynapi_common_object_fields ();
11418 for (f = &fields[0]; f->name; f++)
11419 {
11420 LOG_INSANE ("-%s.%s [%d %s] vs %d\n",
11421 is_entity ? "ENTITY" : "OBJECT", f->name, f->dxf,
11422 f->type, pair->code)
11423 if ((pair->code == 62 || pair->code == 420
11424 || pair->code == 430 || pair->code == 440)
11425 && (f->size > 8
11426 && strEQc (f->type, "CMC"))) // alt. color fields
11427 {
11428 BITCODE_CMC color;
11429 dwg_dynapi_common_value (_obj, f->name, &color, NULL);
11430 if (pair->code == 62)
11431 {
11432 color.index = pair->value.i;
11433 LOG_TRACE ("COMMON.%s.index = %d [%s %d]\n", f->name,
11434 pair->value.i, "CMC", pair->code);
11435 }
11436 else if (pair->code == 420)
11437 {
11438 color.rgb = pair->value.l;
11439 color.method = pair->value.l >> 0x18;
11440 if (pair->value.l == 257)
11441 {
11442 color.method = 0xc8;
11443 color.rgb = 0xc8000000;
11444 }
11445 // color.alpha = (pair->value.l & 0xFF000000) >> 24;
11446 // if (color.alpha)
11447 // color.alpha_type = 3;
11448 LOG_TRACE ("COMMON.%s.rgb = %08X [%s %d]\n", f->name,
11449 pair->value.u, "CMC", pair->code);
11450 }
11451 else if (pair->code == 440)
11452 {
11453 color.flag |= 0x20;
11454 color.alpha = (pair->value.l & 0xFF000000) >> 24;
11455 color.alpha_type = pair->value.u >> 8;
11456 if (color.alpha && !color.alpha_type)
11457 color.alpha_type = 3;
11458 LOG_TRACE ("COMMON.%s.alpha = %08X [%s %d]\n",
11459 f->name, pair->value.u, "CMC",
11460 pair->code);
11461 }
11462 else if (pair->code == 430)
11463 {
11464 color.flag |= 0x10;
11465 color.name = dwg_add_u8_input (dwg, pair->value.s);
11466 // TODO: book_name or name?
11467 LOG_TRACE ("COMMON.%s.name = %s [%s %d]\n", f->name,
11468 pair->value.s, "CMC", pair->code);
11469 }
11470 dwg_dynapi_common_set_value (_obj, f->name, &color,
11471 is_tu);
11472 goto next_pair; // found, early exit
11473 }
11474 else if (f->dxf == pair->code)
11475 {
11476 /// resolve handle (table entry) given by name or ref
11477 if (strEQc (f->type, "H"))
11478 {
11479 BITCODE_H handle = find_tablehandle (dwg, pair);
11480 if (!handle)
11481 {
11482 if (pair->code > 300)
11483 {
11484 handle = dwg_add_handleref (
11485 dwg, 5, pair->value.u, obj);
11486 dwg_dynapi_common_set_value (_obj, f->name,
11487 &handle, 0);
11488 LOG_TRACE ("COMMON.%s = %X [H %d]\n",
11489 f->name, pair->value.u,
11490 pair->code)
11491 }
11492 else
11493 {
11494 LOG_WARN ("TODO resolve common handle "
11495 "name %s %s",
11496 f->name, pair->value.s)
11497 }
11498 }
11499 else
11500 {
11501 if (pair->code > 300)
11502 LOG_TRACE ("COMMON.%s = %lX [H %d]\n", f->name,
11503 pair->value.l, pair->code)
11504 else
11505 LOG_TRACE ("COMMON.%s = %s [H %d]\n", f->name,
11506 pair->value.s, pair->code)
11507 dwg_dynapi_common_set_value (_obj, f->name,
11508 &handle, 0);
11509 }
11510 if (is_entity && pair->code == 6 && pair->value.s
11511 && dwg->header.version >= R_2000)
11512 {
11513 BITCODE_BB flags = 3;
11514 if (!strcasecmp (pair->value.s, "BYLAYER"))
11515 flags = 0;
11516 if (!strcasecmp (pair->value.s, "BYBLOCK"))
11517 flags = 1;
11518 if (!strcasecmp (pair->value.s, "CONTINUOUS"))
11519 flags = 2;
11520 dwg_dynapi_common_set_value (_obj, "ltype_flags",
11521 &flags, 0);
11522 LOG_TRACE ("COMMON.%s = %d [BB 0]\n",
11523 "ltype_flags", flags);
11524 }
11525 if (is_entity && pair->code == 390
11526 && dwg->header.version >= R_2000)
11527 {
11528 BITCODE_BB flags = 3;
11529 /*
11530 if (!strcasecmp (pair->value.s, "BYLAYER"))
11531 flags = 0;
11532 if (!strcasecmp (pair->value.s, "BYBLOCK"))
11533 flags = 1;
11534 */
11535 dwg_dynapi_common_set_value (
11536 _obj, "plotstyle_flags", &flags, 0);
11537 LOG_TRACE ("COMMON.%s = %d [BB 0]\n",
11538 "plotstyle_flags", flags);
11539 }
11540 if (is_entity && pair->code == 347
11541 && dwg->header.version >= R_2007)
11542 {
11543 BITCODE_BB flags = 3;
11544 /*
11545 if (!strcasecmp (pair->value.s, "BYLAYER"))
11546 flags = 0;
11547 if (!strcasecmp (pair->value.s, "BYBLOCK"))
11548 flags = 1;
11549 */
11550 dwg_dynapi_common_set_value (
11551 _obj, "material_flags", &flags, 0);
11552 LOG_TRACE ("COMMON.%s = %d [BB 0]\n",
11553 "material_flags", flags);
11554 }
11555 goto next_pair; // found, early exit
11556 }
11557 else if (pair->code == 310 && is_entity
11558 && !obj->tio.entity->preview_size
11559 && obj->fixedtype > DWG_TYPE_LAYOUT
11560 && strEQc (subclass, "AcDbEntity"))
11561 {
11562 pair = add_ent_preview (obj, dat, pair);
11563 goto start_loop;
11564 }
11565 else if (pair->code == 310 && is_entity
11566 && obj->tio.entity->preview_size
11567 && obj->fixedtype > DWG_TYPE_LAYOUT
11568 && strEQc (subclass, "AcDbEntity"))
11569 {
11570 // This would corrupt the previous preview chain,
11571 // don't append
11572 LOG_ERROR ("Skip duplicate/interrupted %s.preview",
11573 obj->name)
11574 goto next_pair;
11575 }
11576 else
11577 {
11578 // Don't write a ptr twice. This will fuckup the
11579 // num_ counter. Just add to 310 preview, when
11580 // prefixed by 92
11581 if (f->is_malloc || f->is_string)
11582 {
11583 char *ptr = NULL;
11584 if (dwg_dynapi_common_value (_obj, f->name, &ptr,
11585 NULL)
11586 && ptr != NULL)
11587 {
11588 LOG_ERROR ("Skip duplicate %s.%s [%s %d]",
11589 obj->name, f->name, f->type,
11590 pair->code)
11591 goto next_pair;
11592 }
11593 }
11594 dwg_dynapi_common_set_value (_obj, f->name,
11595 &pair->value, 1);
11596 if (f->is_string)
11597 {
11598 LOG_TRACE ("COMMON.%s = %s [%s %d]\n", f->name,
11599 pair->value.s, f->type, pair->code)
11600 }
11601 else
11602 {
11603 if (is_entity && pair->code == 160
11604 && dwg->header.from_version >= R_2010)
11605 {
11606 pair = add_ent_preview (obj, dat, pair);
11607 goto start_loop; // already fresh pair
11608 }
11609 if (strchr (f->type, 'D'))
11610 LOG_TRACE ("COMMON.%s = %f [%s %d]\n", f->name,
11611 pair->value.d, f->type, pair->code)
11612 else
11613 LOG_TRACE ("COMMON.%s = %ld [%s %d]\n",
11614 f->name, pair->value.l, f->type,
11615 pair->code)
11616 }
11617 goto next_pair; // found, early exit
11618 }
11619 }
11620 }
11621 LOG_INSANE ("----\n")
11622 // still needed? already handled above
11623 // not in dynapi: 92 as 310 size prefix for PROXY vector preview
11624 // FIXME 92 is just for pre-r2010 entities. r2010+ is 160
11625 if (pair->code == 92 && is_entity && dwg->header.from_version < R_2010
11626 && (strEQc (subclass, "AcDbEntity")
11627 || strEQc (subclass, "AcDbProxyEntity")
11628 || strstr (subclass, "Surface")))
11629 {
11630 pair = add_ent_preview (obj, dat, pair);
11631 goto start_loop;
11632 }
11633 else if (strEQc (name, "MULTILEADER"))
11634 {
11635 // for the unknown subfields: 300, 140, 145, 302, 304, ...
11636 pair = add_MULTILEADER (obj, dat, pair);
11637 // returns with 0 or 301
11638 if (pair && pair->code == 301)
11639 goto next_pair;
11640 }
11641 else if (obj->fixedtype == DWG_TYPE_TABLESTYLE)
11642 {
11643 // for the unknown subfields: 7, 140, ...
11644 pair = add_TABLESTYLE (obj, dat, pair);
11645 // returns with 0
11646 if (pair && pair->code == 0)
11647 goto start_loop;
11648 }
11649 else if (obj->fixedtype == DWG_TYPE_TABLEGEOMETRY)
11650 {
11651 // for the unknown subfields: 93, 40, ...
11652 pair = add_TABLEGEOMETRY_Cell (obj, dat, pair);
11653 // returns with 0
11654 if (pair && pair->code == 0)
11655 goto start_loop;
11656 }
11657 else if (strEQc (name, "BLOCK")
11658 && (pair->code == 70 || pair->code == 10
11659 || pair->code == 20 || pair->code == 30
11660 || pair->code == 3 || pair->code == 1
11661 || pair->code == 4))
11662 ; // ignore those BLOCK fields. DXF artifacts
11663 else if (strEQc (name, "DIMENSION")
11664 && (pair->code == 2 || pair->code == 210
11665 || pair->code == 220 || pair->code == 230))
11666 ; // ignore the POLYLINE elevation.x,y. DXF artifacts
11667 else if (strEQc (name, "HATCH")
11668 && (pair->code == 10 || pair->code == 20))
11669 ; // ignore the whole PLINE and VERTEX_PFACE_FACE 3BD 10
11670 else if ((strEQc (name, "VERTEX_PFACE_FACE")
11671 || strEQc (name, "POLYLINE_3D")
11672 || strEQc (name, "POLYLINE_2D")
11673 || strEQc (name, "POLYLINE_MESH")
11674 || strEQc (name, "POLYLINE_PFACE"))
11675 && (pair->code == 10 || pair->code == 20
11676 || pair->code == 30))
11677 ; // ignore the POLYLINE_PFACE flag 70
11678 else if (pair->code == 70 && strEQc (name, "POLYLINE_PFACE"))
11679 ;
11680 // always OLE
11681 else if (pair->code == 1 && strEQc (name, "OLE2FRAME")
11682 && strEQc (pair->value.s, "OLE"))
11683 ;
11684 // the STYLE name, which is already defined by code 7
11685 else if (pair->code == 2 && strEQc (name, "SHAPE"))
11686 ;
11687 else if ((pair->code == 290 || pair->code == 2)
11688 && ((obj->fixedtype == DWG_TYPE_REGION)
11689 || (obj->fixedtype == DWG_TYPE_BODY)
11690 || (obj->fixedtype == DWG_TYPE__3DSOLID)))
11691 LOG_TRACE ("Unknown DXF code %d for %s\n", pair->code, name)
11692 else if (obj->fixedtype == DWG_TYPE_PROXY_ENTITY
11693 && pair->code == 92)
11694 {
11695 pair = add_ent_preview (obj, dat, pair);
11696 goto start_loop;
11697 }
11698 else if (obj->fixedtype == DWG_TYPE_PROXY_ENTITY
11699 && (pair->code == 90 || pair->code == 91
11700 || pair->code == 71
11701 || pair->code == 94)) // unknown r14
11702 {
11703 Dwg_Entity_PROXY_ENTITY *o
11704 = obj->tio.entity->tio.PROXY_ENTITY;
11705 if (dwg->header.version <= R_14)
11706 {
11707 if (pair->code == 90)
11708 o->class_id = pair->value.i;
11709 else if (pair->code == 91)
11710 o->version = pair->value.i;
11711 }
11712 else if (pair->code == 91)
11713 o->class_id = pair->value.i;
11714 else if (pair->code == 71) // r2018+
11715 o->version = pair->value.i;
11716 }
11717 else if (obj->fixedtype == DWG_TYPE_LAYER
11718 && ((pair->code == 348) || (pair->code == 420)
11719 || (pair->code == 430) | (pair->code == 440)))
11720 {
11721 Dwg_Object_LAYER *o = obj->tio.object->tio.LAYER;
11722 if (pair->code == 420)
11723 {
11724 o->color.rgb = pair->value.l;
11725 o->color.method = pair->value.l >> 0x18;
11726 if (pair->value.l == 257)
11727 {
11728 o->color.method = 0xc8;
11729 o->color.rgb = 0xc8000000;
11730 }
11731 // o->color.alpha = (pair->value.l & 0xFF000000) >> 24;
11732 // if (o->color.alpha)
11733 // o->color.alpha_type = 3;
11734 LOG_TRACE ("%s.color.rgb = %08X [%s %d]\n", name,
11735 pair->value.u, "CMC", pair->code);
11736 }
11737 else if (pair->code == 440)
11738 {
11739 o->color.flag |= 0x20; // ???
11740 o->color.alpha = (pair->value.l & 0xFF000000) >> 24;
11741 o->color.alpha_type = pair->value.u >> 8;
11742 if (o->color.alpha && !o->color.alpha_type)
11743 o->color.alpha_type = 3;
11744 LOG_TRACE ("%s.color.alpha = %08X [%s %d]\n", name,
11745 pair->value.u, "CMC", pair->code);
11746 }
11747 else if (pair->code == 430)
11748 {
11749 char *x;
11750 o->color.book_name = strdup (pair->value.s);
11751 x = strchr (o->color.book_name, '$');
11752 if (!x) // name only
11753 {
11754 o->color.name = o->color.book_name;
11755 o->color.flag = 1;
11756 LOG_TRACE ("%s.color.name = %s [%s %d]\n", name,
11757 pair->value.s, "CMC", pair->code);
11758 if (dwg->header.version >= R_2007)
11759 {
11760 char *tmp = o->color.name;
11761 o->color.name
11762 = (BITCODE_T)bit_utf8_to_TU (o->color.name, 0);
11763 free (tmp);
11764 }
11765 }
11766 else
11767 { // book with name
11768 o->color.flag = 3;
11769 o->color.name = strdup (x + 1);
11770 x[0] = '\0';
11771 if (dwg->header.version >= R_2007)
11772 {
11773 char *tmp = o->color.book_name;
11774 o->color.book_name = (BITCODE_T)bit_utf8_to_TU (
11775 o->color.book_name, 0);
11776 free (tmp);
11777 tmp = o->color.name;
11778 o->color.name
11779 = (BITCODE_T)bit_utf8_to_TU (o->color.name, 0);
11780 free (tmp);
11781 }
11782 LOG_TRACE ("%s.color.book+name = %s [%s %d]\n", name,
11783 pair->value.s, "CMC", pair->code);
11784 }
11785 }
11786 else if (pair->code == 348)
11787 LOG_TRACE ("Unknown DXF code %d for %s\n", pair->code,
11788 name);
11789 goto next_pair;
11790 }
11791 else if (obj->fixedtype == DWG_TYPE_DIMSTYLE
11792 && pair->code == 287)
11793 {
11794 // <= r14
11795 Dwg_Object_DIMSTYLE *o = obj->tio.object->tio.DIMSTYLE;
11796 o->DIMFIT = pair->value.i;
11797 LOG_TRACE ("%s.DIMFIT = %d [%s %d]\n", name, pair->value.i,
11798 "RC", pair->code);
11799 }
11800 else if (obj->fixedtype == DWG_TYPE_DIMENSION_ALIGNED
11801 && pair->code == 52)
11802 {
11803 BITCODE_BD ang = deg2rad (pair->value.d);
11804 free (obj->dxfname);
11805 UPGRADE_ENTITY (DIMENSION_ALIGNED, DIMENSION_LINEAR)
11806 dwg_dynapi_entity_set_value (_obj, "DIMENSION_LINEAR",
11807 "ext_line_rotation", &ang, 1);
11808 LOG_TRACE ("%s.%s = %f (from DEG %f°) [%s %d]\n", name,
11809 "ext_line_rotation", ang, pair->value.d, "BD",
11810 52);
11811 }
11812 else if (obj->fixedtype == DWG_TYPE_DIMENSION_ALIGNED
11813 && pair->code == 50)
11814 {
11815 BITCODE_BD ang = deg2rad (pair->value.d);
11816 free (obj->dxfname);
11817 UPGRADE_ENTITY (DIMENSION_ALIGNED, DIMENSION_LINEAR)
11818 dwg_dynapi_entity_set_value (_obj, "DIMENSION_LINEAR",
11819 "dim_rotation", &ang, 1);
11820 LOG_TRACE ("%s.%s = %f (from DEG %f°) [%s %d]\n", name,
11821 "dim_rotation", ang, pair->value.d, "BD", 50);
11822 }
11823 // accept wrong colors
11824 else if (is_class_stable (obj->name) && (pair->code < 60 || pair->code > 68))
11825 {
11826 goto invalid_dxf;
11827 }
11828 else
11829 LOG_WARN ("Unknown DXF code %d for %s", pair->code, name);
11830 }
11831 }
11832 next_pair:
11833 dxf_free_pair (pair);
11834 pair = dxf_read_pair (dat);
11835 DXF_RETURN_EOF (pair);
11836 }
11837
11838 if (obj->type == DWG_TYPE_SEQEND)
11839 dxf_postprocess_SEQEND (obj);
11840 else if (obj->type == DWG_TYPE_LAYOUT)
11841 dxf_postprocess_LAYOUT (obj);
11842 else if (obj->type == DWG_TYPE_PLOTSETTINGS)
11843 dxf_postprocess_PLOTSETTINGS (obj);
11844 // set defaults not in dxf:
11845 else if (obj->type == DWG_TYPE__3DFACE && dwg->header.version >= R_2000)
11846 {
11847 Dwg_Entity__3DFACE *o = obj->tio.entity->tio._3DFACE;
11848 o->has_no_flags = 1;
11849 LOG_TRACE ("_3DFACE.has_no_flags = 1 [B]\n");
11850 }
11851 else if (is_textlike (obj))
11852 postprocess_TEXTlike (obj);
11853
11854 return pair;
11855
11856 invalid_dxf:
11857 LOG_ERROR ("Invalid DXF code %d for %s", pair->code, name)
11858 dxf_free_pair (pair);
11859 return NULL;
11860 }
11861
11862 static int
dxf_tables_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)11863 dxf_tables_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
11864 {
11865 char table[80];
11866 Dxf_Pair *pair = dxf_read_pair (dat);
11867
11868 table[0] = '\0'; // init
11869 while (pair) // read next 0 TABLE
11870 {
11871 if (pair->code == 0 && pair->value.s) // TABLE or ENDTAB
11872 {
11873 if (strEQc (pair->value.s, "TABLE"))
11874 table[0] = '\0'; // new table coming up
11875 else if (strEQc (pair->value.s, "BLOCK_RECORD"))
11876 {
11877 strncpy (table, pair->value.s, 79);
11878 table[79] = '\0';
11879 }
11880 else if (strEQc (pair->value.s, "ENDTAB"))
11881 table[0] = '\0'; // close table
11882 else if (strEQc (pair->value.s, "ENDSEC"))
11883 {
11884 dxf_free_pair (pair);
11885 return 0;
11886 }
11887 else
11888 {
11889 LOG_ERROR ("Unknown 0 %s (%s)", pair->value.s, "tables");
11890 dxf_free_pair (pair);
11891 return 1;
11892 }
11893 }
11894 else if (pair->code == 2 && pair->value.s && strlen (pair->value.s) < 80
11895 && is_table_name (pair->value.s)) // new table NAME
11896 {
11897 BITCODE_BL i = 0;
11898 BITCODE_BL ctrl_id;
11899 strncpy (table, pair->value.s, 79);
11900 table[79] = '\0';
11901 pair = new_table_control (table, dat, dwg); // until 0 table
11902 ctrl_id = dwg->num_objects - 1; // dwg->object might move
11903 while (pair && pair->code == 0 && pair->value.s
11904 && strEQ (pair->value.s, table))
11905 {
11906 char *dxfname = strdup (pair->value.s);
11907 dxf_free_pair (pair);
11908 // until 0 table or 0 ENDTAB
11909 pair = new_object (table, dxfname, dat, dwg, ctrl_id, &i);
11910 if (!pair)
11911 return DWG_ERR_INVALIDDWG;
11912 // undo BLOCK_CONTROL.entries and LTYPE_CONTROL.entries
11913 if (strEQc (table, "BLOCK_RECORD"))
11914 {
11915 Dwg_Object *obj = &dwg->object[dwg->num_objects - 1];
11916 Dwg_Object *ctrl = &dwg->object[ctrl_id];
11917 Dwg_Object_BLOCK_CONTROL *_ctrl
11918 = ctrl->tio.object->tio.BLOCK_CONTROL;
11919 if (_ctrl->model_space
11920 && obj->handle.value == _ctrl->model_space->absolute_ref)
11921 i--;
11922 else if (_ctrl->paper_space
11923 && obj->handle.value
11924 == _ctrl->paper_space->absolute_ref)
11925 i--;
11926 }
11927 else if (strEQc (table, "LTYPE"))
11928 {
11929 Dwg_Object *obj = &dwg->object[dwg->num_objects - 1];
11930 Dwg_Object_LTYPE *_obj = obj->tio.object->tio.LTYPE;
11931 Dwg_Object *ctrl = &dwg->object[ctrl_id];
11932 Dwg_Object_LTYPE_CONTROL *_ctrl
11933 = ctrl->tio.object->tio.LTYPE_CONTROL;
11934 if (_ctrl->bylayer
11935 && obj->handle.value == _ctrl->bylayer->absolute_ref)
11936 i--;
11937 else if (_ctrl->byblock
11938 && obj->handle.value
11939 == _ctrl->byblock->absolute_ref)
11940 i--;
11941 else if (dwg->header.version > R_2004 && _obj->name
11942 && _obj->has_strings_area)
11943 {
11944 _obj->strings_area = (BITCODE_TF)xcalloc (512, 1);
11945 if (!_obj->strings_area)
11946 goto outofmem;
11947 }
11948 if (dwg->header.version <= R_2004)
11949 {
11950 _obj->strings_area = (BITCODE_TF)xcalloc (256, 1);
11951 if (!_obj->strings_area)
11952 goto outofmem;
11953 }
11954 }
11955 }
11956 // next table
11957 // fixup entries vs num_entries (no NULL entries)
11958 {
11959 Dwg_Object *ctrl = &dwg->object[ctrl_id];
11960 Dwg_Object_BLOCK_CONTROL *_ctrl
11961 = ctrl->tio.object->tio.BLOCK_CONTROL;
11962 int at_end = 1;
11963 unsigned num_entries = _ctrl->num_entries;
11964 if (_ctrl)
11965 {
11966 for (int j = num_entries - 1; j >= 0; j--)
11967 {
11968 BITCODE_H ref = _ctrl->entries[j];
11969 if (!ref)
11970 {
11971 if (at_end)
11972 {
11973 num_entries--;
11974 }
11975 else
11976 {
11977 _ctrl->entries[j]
11978 = dwg_add_handleref (dwg, 2, 0, NULL);
11979 LOG_TRACE ("%s.entries[%d] = (2.0.0)\n",
11980 ctrl->name, j);
11981 }
11982 }
11983 else
11984 at_end = 0;
11985 }
11986 // remove many empty entries at the end at once (avoids DDOS)
11987 if (num_entries != _ctrl->num_entries)
11988 {
11989 _ctrl->entries = (BITCODE_H *)realloc (
11990 _ctrl->entries, num_entries * sizeof (BITCODE_H));
11991 if (num_entries && !_ctrl->entries)
11992 goto outofmem;
11993 _ctrl->num_entries = num_entries;
11994 LOG_TRACE ("%s.num_entries => %d\n", ctrl->name,
11995 _ctrl->num_entries);
11996 }
11997 // leave room for one active entry
11998 if (_ctrl->num_entries == 1 && !_ctrl->entries[0])
11999 {
12000 _ctrl->entries[0] = dwg_add_handleref (dwg, 2, 0, NULL);
12001 LOG_TRACE ("%s.entries[0] = (2.0.0)\n", ctrl->name);
12002 }
12003 }
12004 }
12005 }
12006 DXF_RETURN_ENDSEC (0) // next TABLE or ENDSEC
12007 dxf_free_pair (pair);
12008 pair = dxf_read_pair (dat);
12009 DXF_CHECK_EOF;
12010 }
12011 dxf_free_pair (pair);
12012 return 0;
12013
12014 outofmem:
12015 dxf_free_pair (pair);
12016 return DWG_ERR_OUTOFMEM;
12017 }
12018
12019 static int
dxf_blocks_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12020 dxf_blocks_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12021 {
12022 char name[80];
12023 Dxf_Pair *pair = dxf_read_pair (dat);
12024
12025 name[0] = '\0'; // init
12026 while (pair) // read next 0 TABLE
12027 {
12028 if (pair != NULL && pair->code == 0 && pair->value.s)
12029 {
12030 BITCODE_BL i = 0;
12031 BITCODE_BB entmode = 0;
12032 while (pair != NULL && pair->code == 0 && pair->value.s
12033 && strNE (pair->value.s, "ENDSEC"))
12034 {
12035 Dwg_Object *obj, *blkhdr = NULL;
12036 BITCODE_BL idx = dwg->num_objects;
12037 char *dxfname = strdup (pair->value.s);
12038 strncpy (name, dxfname, 79);
12039 name[79] = '\0';
12040 entity_alias (name);
12041 dxf_free_pair (pair);
12042 pair = new_object (name, dxfname, dat, dwg, 0, &i);
12043 if (!pair)
12044 return DWG_ERR_INVALIDDWG;
12045 obj = &dwg->object[idx];
12046 if (obj->type == DWG_TYPE_BLOCK)
12047 {
12048 Dwg_Object_Entity *ent = obj->tio.entity;
12049 Dwg_Entity_BLOCK *_obj = obj->tio.entity->tio.BLOCK;
12050 i = 0;
12051 if (ent->ownerhandle
12052 && (blkhdr = dwg_ref_object (dwg, ent->ownerhandle)))
12053 {
12054 if (blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER)
12055 {
12056 Dwg_Object_BLOCK_HEADER *_hdr
12057 = blkhdr->tio.object->tio.BLOCK_HEADER;
12058 ent->ownerhandle->obj = NULL; // still dirty
12059 _hdr->block_entity = dwg_add_handleref (
12060 dwg, 3, obj->handle.value, blkhdr);
12061 LOG_TRACE ("BLOCK_HEADER.block_entity = " FORMAT_REF
12062 " [H] (blocks)\n",
12063 ARGS_REF (_hdr->block_entity));
12064 }
12065 else if (blkhdr->fixedtype == DWG_TYPE_BLOCK_CONTROL)
12066 {
12067 Dwg_Object_BLOCK_CONTROL *_ctrl
12068 = blkhdr->tio.object->tio.BLOCK_CONTROL;
12069 ent->ownerhandle->obj = NULL; // still dirty
12070 if (!_ctrl->model_space && _obj->name
12071 && bit_eq_T (dat, _obj->name, "*Model_Space"))
12072 {
12073 _ctrl->model_space = dwg_add_handleref (
12074 dwg, 3, obj->handle.value, blkhdr);
12075 LOG_TRACE (
12076 "BLOCK_CONTROL.model_space = " FORMAT_REF
12077 " [H] (blocks)\n",
12078 ARGS_REF (_ctrl->model_space));
12079 }
12080 else if (!_ctrl->paper_space && _obj->name
12081 && bit_eq_T (dat, _obj->name, "*Paper_Space"))
12082 {
12083 _ctrl->paper_space = dwg_add_handleref (
12084 dwg, 3, obj->handle.value, blkhdr);
12085 LOG_TRACE (
12086 "BLOCK_CONTROL.paper_space = " FORMAT_REF
12087 " [H] (blocks)\n",
12088 ARGS_REF (_ctrl->paper_space));
12089 }
12090 }
12091 }
12092 else
12093 blkhdr = NULL;
12094 if (!_obj || !_obj->name)
12095 ;
12096 else if (bit_eq_T (dat, _obj->name, "*Model_Space"))
12097 entmode = ent->entmode = 2;
12098 else if (bit_eq_T (dat, _obj->name, "*Paper_Space"))
12099 entmode = ent->entmode = 1;
12100 else
12101 entmode = 0;
12102 }
12103 else if (obj->type == DWG_TYPE_ENDBLK)
12104 {
12105 Dwg_Object_Entity *ent = obj->tio.entity;
12106 Dwg_Entity_BLOCK *_obj = obj->tio.entity->tio.BLOCK;
12107 ent->entmode = entmode;
12108 LOG_TRACE ("%s.entmode = %d [BB] (blocks)\n", obj->name,
12109 entmode);
12110 entmode = 0;
12111 // set BLOCK_HEADER.endblk_entity handle
12112 if ((blkhdr = dwg_ref_object (dwg, ent->ownerhandle))
12113 && blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER)
12114 {
12115 Dwg_Object *prev_entity;
12116 Dwg_Object_BLOCK_HEADER *_hdr
12117 = blkhdr->tio.object->tio.BLOCK_HEADER;
12118 ent->ownerhandle->obj = NULL; // still dirty
12119 _hdr->endblk_entity = dwg_add_handleref (
12120 dwg, 3, obj->handle.value, blkhdr);
12121 LOG_TRACE ("BLOCK_HEADER.endblk_entity = " FORMAT_REF
12122 " [H] (blocks)\n",
12123 ARGS_REF (_hdr->endblk_entity));
12124
12125 if ((prev_entity = find_prev_entity (obj)))
12126 {
12127 _hdr->last_entity = dwg_add_handleref (
12128 dwg, 4, prev_entity->handle.value, NULL);
12129 LOG_TRACE ("BLOCK_HEADER.last_entity = " FORMAT_REF
12130 " [H] (blocks)\n",
12131 ARGS_REF (_hdr->last_entity));
12132 }
12133 }
12134 }
12135 // normal entity
12136 else if (obj->supertype == DWG_SUPERTYPE_ENTITY)
12137 {
12138 Dwg_Object_Entity *ent = obj->tio.entity;
12139 Dwg_Object_BLOCK_HEADER *_hdr;
12140 ent->entmode = entmode;
12141 LOG_TRACE ("%s.entmode = %d [BB] (blocks)\n", obj->name,
12142 entmode);
12143 // add to entities
12144 if (ent->ownerhandle
12145 && (blkhdr = dwg_ref_object (dwg, ent->ownerhandle))
12146 && blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER
12147 && (_hdr = blkhdr->tio.object->tio.BLOCK_HEADER))
12148 {
12149 BITCODE_H ref = dwg_add_handleref (
12150 dwg, 3, obj->handle.value, NULL);
12151 PUSH_HV (_hdr, num_owned, entities, ref)
12152 }
12153 if (ent->ownerhandle
12154 && (dwg->header.version >= R_13
12155 || dwg->header.version == R_INVALID)
12156 /* requires target version being set */
12157 && dwg->header.version < R_2004
12158 && (blkhdr = dwg_ref_object (dwg, ent->ownerhandle))
12159 && blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER
12160 && (_hdr = blkhdr->tio.object->tio.BLOCK_HEADER)
12161 && !_hdr->first_entity)
12162 {
12163 _hdr->first_entity = dwg_add_handleref (
12164 dwg, 4, obj->handle.value, NULL);
12165 LOG_TRACE ("BLOCK_HEADER.first_entity = " FORMAT_REF
12166 " [H] (blocks)\n",
12167 ARGS_REF (_hdr->first_entity));
12168 }
12169 }
12170 }
12171 DXF_RETURN_ENDSEC (0) // next BLOCK or ENDSEC
12172 }
12173 dxf_free_pair (pair);
12174 pair = dxf_read_pair (dat);
12175 DXF_CHECK_EOF;
12176 }
12177 dxf_free_pair (pair);
12178 return 0;
12179 }
12180
12181 // register this block entity, e.g. ModelSpace with the BLOCK_HEADER
12182 // TODO use this also in the BLOCKS section, not just ENTITIES
12183 static void
add_to_BLOCK_HEADER(Dwg_Object * restrict obj,Dwg_Object_Ref * restrict ownerhandle)12184 add_to_BLOCK_HEADER (Dwg_Object *restrict obj,
12185 Dwg_Object_Ref *restrict ownerhandle)
12186 {
12187 Dwg_Data *dwg = obj->parent;
12188 Dwg_Object_BLOCK_HEADER *_ctrl;
12189 Dwg_Object *ctrl = dwg_ref_object (dwg, ownerhandle);
12190
12191 if (!ctrl || ctrl->type != DWG_TYPE_BLOCK_HEADER)
12192 return;
12193 _ctrl = ctrl->tio.object->tio.BLOCK_HEADER;
12194 if (obj->supertype != DWG_SUPERTYPE_ENTITY)
12195 return;
12196 LOG_TRACE ("add_to_BLOCK_HEADER %s: %s [%lX]\n", _ctrl->name, obj->name,
12197 obj->handle.value);
12198 if (obj->type == DWG_TYPE_ENDBLK)
12199 {
12200 if (!_ctrl->endblk_entity)
12201 _ctrl->endblk_entity
12202 = dwg_add_handleref (dwg, 3, obj->handle.value, ctrl);
12203 return;
12204 }
12205 if (obj->type == DWG_TYPE_BLOCK)
12206 {
12207 if (!_ctrl->block_entity)
12208 _ctrl->block_entity
12209 = dwg_add_handleref (dwg, 3, obj->handle.value, ctrl);
12210 return;
12211 }
12212 if (!_ctrl->first_entity)
12213 _ctrl->last_entity = _ctrl->first_entity
12214 = dwg_add_handleref (dwg, 4, obj->handle.value, NULL);
12215 else
12216 // always overwrite. and it is global, so we can reuse it.
12217 _ctrl->last_entity = dwg_add_handleref (dwg, 4, obj->handle.value, NULL);
12218 PUSH_HV (_ctrl, num_owned, entities, _ctrl->last_entity);
12219 }
12220
12221 static int
dxf_entities_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12222 dxf_entities_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12223 {
12224 Dxf_Pair *pair = dxf_read_pair (dat);
12225 char name[80];
12226 unsigned long mspace
12227 = dwg->header_vars.BLOCK_RECORD_MSPACE
12228 ? dwg->header_vars.BLOCK_RECORD_MSPACE->absolute_ref
12229 : 0x1F;
12230 unsigned long pspace
12231 = dwg->header_vars.BLOCK_RECORD_PSPACE
12232 ? dwg->header_vars.BLOCK_RECORD_PSPACE->absolute_ref
12233 : 0UL;
12234 BITCODE_H mspace_ref = dwg_model_space_ref (dwg);
12235
12236 while (pair != NULL && pair->code == 0 && pair->value.s)
12237 {
12238 strncpy (name, pair->value.s, 79);
12239 name[79] = '\0';
12240 entity_alias (name);
12241 // until 0 ENDSEC
12242 while (pair != NULL && pair->code == 0 && pair->value.s
12243 && (is_dwg_entity (name) || strEQc (name, "DIMENSION")))
12244 {
12245 char *dxfname = strdup (pair->value.s);
12246 dxf_free_pair (pair);
12247 pair = new_object (name, dxfname, dat, dwg, 0, NULL);
12248 if (!pair)
12249 return DWG_ERR_INVALIDDWG;
12250 if (pair->code == 0 && pair->value.s)
12251 {
12252 Dwg_Object *obj = &dwg->object[dwg->num_objects - 1];
12253 Dwg_Object_Entity *ent = obj->tio.entity;
12254 if (ent->ownerhandle)
12255 {
12256 if (ent->ownerhandle->absolute_ref == mspace)
12257 ent->entmode = 2;
12258 else if (pspace && ent->ownerhandle->absolute_ref == pspace)
12259 ent->entmode = 1;
12260 add_to_BLOCK_HEADER (obj, ent->ownerhandle);
12261 }
12262 else
12263 {
12264 ent->entmode = 2;
12265 add_to_BLOCK_HEADER (obj, mspace_ref);
12266 }
12267
12268 in_postprocess_handles (obj);
12269 strncpy (name, pair->value.s, 79);
12270 name[79] = '\0';
12271 entity_alias (name);
12272 }
12273 }
12274 DXF_RETURN_ENDSEC (0)
12275 else
12276 LOG_WARN ("Unhandled 0 %s (%s)", name, "entities");
12277 dxf_free_pair (pair);
12278 pair = dxf_read_pair (dat);
12279 DXF_CHECK_EOF;
12280 }
12281 dxf_free_pair (pair);
12282 return 0;
12283 }
12284
12285 static int
dxf_objects_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12286 dxf_objects_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12287 {
12288 char name[80];
12289 Dxf_Pair *pair = dxf_read_pair (dat);
12290 while (pair != NULL)
12291 {
12292 while (pair != NULL && pair->code == 0 && pair->value.s)
12293 {
12294 strncpy (name, pair->value.s, 79);
12295 name[79] = '\0';
12296 object_alias (name);
12297 if (is_dwg_object (name))
12298 {
12299 char *dxfname = strdup (pair->value.s);
12300 dxf_free_pair (pair);
12301 pair = new_object (name, dxfname, dat, dwg, 0, NULL);
12302 if (!pair)
12303 return DWG_ERR_INVALIDDWG;
12304 }
12305 else
12306 {
12307 DXF_RETURN_ENDSEC (0);
12308 LOG_WARN ("Unhandled 0 %s (%s)", name, "objects");
12309 dxf_free_pair (pair);
12310 pair = dxf_read_pair (dat);
12311 DXF_CHECK_EOF;
12312 }
12313 }
12314 dxf_free_pair (pair);
12315 pair = dxf_read_pair (dat);
12316 DXF_CHECK_EOF;
12317 }
12318 dxf_free_pair (pair);
12319 return 0;
12320 }
12321
12322 // redirected from ACDSDATA for now
12323 static int
dxf_unknownsection_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12324 dxf_unknownsection_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12325 {
12326 Dxf_Pair *pair = dxf_read_pair (dat);
12327 // until 0 ENDSEC
12328 while (pair)
12329 {
12330 while (pair && pair->code == 0 && pair->value.s)
12331 {
12332 DXF_RETURN_ENDSEC (0);
12333 LOG_WARN ("Unhandled 0 %s (%s)", pair->value.s, "unknownsection");
12334 dxf_free_pair (pair);
12335 pair = dxf_read_pair (dat);
12336 DXF_CHECK_EOF;
12337 }
12338 dxf_free_pair (pair);
12339 pair = dxf_read_pair (dat);
12340 DXF_CHECK_EOF;
12341 }
12342 dxf_free_pair (pair);
12343 return DWG_ERR_INVALIDTYPE;
12344 }
12345
12346 // read to THUMBNAIL dwg->thumbnail, size 90. not entity->preview
12347 static int
dxf_thumbnail_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12348 dxf_thumbnail_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12349 {
12350 Dxf_Pair *pair = dxf_read_pair (dat);
12351 unsigned written = 0;
12352
12353 while (pair)
12354 {
12355 switch (pair->code)
12356 {
12357 case 0: // ENDSEC
12358 dxf_free_pair (pair);
12359 return 0;
12360 case 90:
12361 dwg->thumbnail.size = pair->value.l; // INT32 => long
12362 dwg->thumbnail.chain
12363 = (unsigned char *)calloc (dwg->thumbnail.size, 1);
12364 if (!dwg->thumbnail.chain)
12365 {
12366 dxf_free_pair (pair);
12367 LOG_ERROR ("Out of memory");
12368 return DWG_ERR_OUTOFMEM;
12369 }
12370 LOG_TRACE ("PREVIEW.size = %ld\n", dwg->thumbnail.size);
12371 break;
12372 case 310:
12373 if (pair->value.s)
12374 {
12375 unsigned len = strlen (pair->value.s);
12376 unsigned blen = len / 2;
12377 unsigned read;
12378 //const char *pos = pair->value.s;
12379 unsigned char *s = &dwg->thumbnail.chain[written];
12380 if (blen + written > dwg->thumbnail.size)
12381 {
12382 dxf_free_pair (pair);
12383 LOG_ERROR ("PREVIEW.size overflow: %u + written %u > "
12384 "size: %lu",
12385 blen, written, dwg->thumbnail.size);
12386 return 1;
12387 }
12388 if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
12389 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
12390 written += read;
12391 LOG_TRACE ("PREVIEW.chain += %u (%u/%lu)\n", blen, written,
12392 dwg->thumbnail.size);
12393 }
12394 break;
12395 default:
12396 LOG_ERROR ("Unknown DXF code %d for %s", pair->code,
12397 "THUMBNAILIMAGE");
12398 break;
12399 }
12400 dxf_free_pair (pair);
12401 pair = dxf_read_pair (dat);
12402 if (!pair)
12403 break;
12404 }
12405 dxf_free_pair (pair);
12406 return 0;
12407 }
12408
12409 // read to AcDs, TODO
12410 // SECTION ACDSDATA: 0 ACDSSCHEMA, 0 ACDSRECORD
12411 static int
dxf_acds_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12412 dxf_acds_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12413 {
12414 // Dxf_Pair *pair = dxf_read_pair (dat);
12415 // unsigned written = 0;
12416 LOG_WARN ("SECTION %s ignored for now", "ACDSDATA");
12417 dxf_unknownsection_read (dat, dwg);
12418 return 0;
12419 }
12420
12421 static void
resolve_postponed_header_refs(Dwg_Data * restrict dwg)12422 resolve_postponed_header_refs (Dwg_Data *restrict dwg)
12423 {
12424 Dwg_Header_Variables *vars = &dwg->header_vars;
12425 uint32_t i;
12426 LOG_TRACE ("resolve %d postponed header ref names:\n", header_hdls->nitems);
12427 for (i = 0; i < header_hdls->nitems; i++)
12428 {
12429 char *field = header_hdls->items[i].field;
12430 Dxf_Pair p = { 0, DWG_VT_STRING };
12431 BITCODE_H hdl = NULL;
12432 p.value.s = header_hdls->items[i].name;
12433 if (!p.value.s || !*p.value.s)
12434 {
12435 LOG_WARN ("HEADER.%s empty dxf:%d", field, (int)p.code);
12436 continue;
12437 }
12438 p.code = header_hdls->items[i].code;
12439 if (strEQc (field, "DIMSTYLE"))
12440 p.code = 3;
12441 else if (strstr (field, "UCS"))
12442 p.code = 345;
12443 hdl = find_tablehandle (dwg, &p);
12444 if (hdl)
12445 {
12446 if (hdl->handleref.code != 5)
12447 hdl = dwg_add_handleref (dwg, 5, hdl->absolute_ref, NULL);
12448 dwg_dynapi_header_set_value (dwg, field, &hdl, 1);
12449 LOG_TRACE ("HEADER.%s %s => " FORMAT_REF " [H %d]\n", field,
12450 p.value.s, ARGS_REF (hdl), (int)p.code);
12451 }
12452 else if (strEQc (field, "CMLSTYLE"))
12453 {
12454 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "MLINESTYLE");
12455 if (hdl)
12456 {
12457 if (hdl->handleref.code != 5)
12458 hdl = dwg_add_handleref (dwg, 5, hdl->absolute_ref, NULL);
12459 dwg_dynapi_header_set_value (dwg, field, &hdl, 1);
12460 LOG_TRACE ("HEADER.%s %s => " FORMAT_REF " [H %d]\n", field,
12461 p.value.s, ARGS_REF (hdl), (int)p.code)
12462 }
12463 else
12464 LOG_WARN ("Unknown HEADER.%s %s dxf:%d", field, p.value.s,
12465 (int)p.code)
12466 }
12467 else
12468 LOG_WARN ("Unknown HEADER.%s %s dxf:%d", field, p.value.s, (int)p.code)
12469 }
12470 }
12471
12472 // i.e. layer or block name
12473 static void
resolve_postponed_object_refs(Dwg_Data * restrict dwg)12474 resolve_postponed_object_refs (Dwg_Data *restrict dwg)
12475 {
12476 uint32_t i;
12477 LOG_TRACE ("resolve %d postponed object ref names:\n", obj_hdls->nitems);
12478 for (i = 0; i < obj_hdls->nitems; i++)
12479 {
12480 char *field = obj_hdls->items[i].field;
12481 Dxf_Pair p = { 0, DWG_VT_STRING };
12482 BITCODE_H hdl = NULL;
12483 int objid = obj_hdls->items[i].code;
12484 Dwg_Object *obj = &dwg->object[objid];
12485 int is_entity = obj->supertype == DWG_SUPERTYPE_ENTITY;
12486
12487 p.value.s = obj_hdls->items[i].name;
12488 if (!p.value.s || !*p.value.s)
12489 {
12490 LOG_WARN ("%s.%s empty", obj->name, field);
12491 continue;
12492 }
12493 // TODO find field type => dxf code
12494 if (strEQc (field, "block_header"))
12495 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "BLOCK");
12496 else if (strEQc (field, "style"))
12497 {
12498 if (is_entity)
12499 p.code = 7;
12500 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "STYLE");
12501 }
12502 else if (strEQc (field, "dimstyle"))
12503 {
12504 if (is_entity)
12505 p.code = 3;
12506 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "DIMSTYLE");
12507 }
12508 else if (strEQc (field, "layer"))
12509 {
12510 if (is_entity)
12511 p.code = 8;
12512 hdl = find_tablehandle (dwg, &p);
12513 }
12514 else if (strEQc (field, "ltype"))
12515 {
12516 if (is_entity)
12517 p.code = 6;
12518 hdl = find_tablehandle (dwg, &p);
12519 }
12520 else if (strEQc (field, "material")
12521 && (is_entity || obj->fixedtype == DWG_TYPE_LAYER))
12522 {
12523 if (is_entity)
12524 p.code = 347;
12525 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "MATERIAL");
12526 }
12527 else if (is_entity && strEQc (field, "shadow"))
12528 {
12529 p.code = 361;
12530 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "SHADOW");
12531 }
12532 else if (strEQc (field, "plotstyle")
12533 && (is_entity || obj->fixedtype == DWG_TYPE_LAYER))
12534 {
12535 if (is_entity)
12536 p.code = 390;
12537 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "PLOTSTYLENAME");
12538 }
12539 else if (is_entity && strEQc (field, "full_visualstyle"))
12540 {
12541 p.code = 348;
12542 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12543 }
12544 else if (is_entity && strEQc (field, "face_visualstyle"))
12545 {
12546 p.code = 348;
12547 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12548 }
12549 else if (is_entity && strEQc (field, "edge_visualstyle"))
12550 {
12551 p.code = 348;
12552 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12553 }
12554 else if (obj->fixedtype == DWG_TYPE_LAYER
12555 && strEQc (field, "visualstyle"))
12556 {
12557 hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12558 }
12559 // TODO: check if DXF by name:
12560 // background, named_ucs, base_ucs, shadeplot, sun, livesection (VIEW,
12561 // VIEWPORT)
12562 else
12563 LOG_WARN ("missing code for %s", field)
12564 if (hdl)
12565 {
12566 Dwg_Object_APPID *_obj = obj->tio.object->tio.APPID;
12567 if (hdl->handleref.code != 5)
12568 hdl = dwg_add_handleref (dwg, 5, hdl->absolute_ref, NULL);
12569 if (p.code > 0)
12570 dwg_dynapi_common_set_value (_obj, field, &hdl, 0);
12571 else
12572 dwg_dynapi_entity_set_value (_obj, obj->name, field, &hdl, 0);
12573 LOG_TRACE ("%s.%s %s => " FORMAT_REF " [H %d]\n", obj->name, field,
12574 p.value.s, ARGS_REF (hdl), (int)p.code);
12575 }
12576 else
12577 LOG_WARN ("Unknown %s.%s %s", obj->name, field, p.value.s)
12578 }
12579 }
12580
12581 #define CHECK_DICTIONARY_HDR(name) \
12582 if (!vars->DICTIONARY_##name) \
12583 { \
12584 vars->DICTIONARY_##name = dwg_find_dictionary (dwg, #name); \
12585 if (vars->DICTIONARY_##name) \
12586 LOG_TRACE ("HEADER.DICTIONARY_" #name " = " FORMAT_REF "\n", \
12587 ARGS_REF (vars->DICTIONARY_##name)) \
12588 else if ((vars->DICTIONARY_##name \
12589 = dwg_find_dictionary (dwg, "ACAD_" #name))) \
12590 LOG_TRACE ("HEADER.DICTIONARY_" #name " = " FORMAT_REF "\n", \
12591 ARGS_REF (vars->DICTIONARY_##name)) \
12592 }
12593
12594 static void
resolve_header_dicts(Dwg_Data * restrict dwg)12595 resolve_header_dicts (Dwg_Data *restrict dwg)
12596 {
12597 Dwg_Header_Variables *vars = &dwg->header_vars;
12598
12599 if (!vars->DICTIONARY_NAMED_OBJECT)
12600 vars->DICTIONARY_NAMED_OBJECT = dwg_add_handleref (dwg, 3, 0xC, NULL);
12601 // only possible after OBJECTS
12602 CHECK_DICTIONARY_HDR (ACAD_GROUP)
12603 CHECK_DICTIONARY_HDR (ACAD_MLINESTYLE)
12604 if (dwg->header.version >= R_2000)
12605 {
12606 CHECK_DICTIONARY_HDR (LAYOUT)
12607 CHECK_DICTIONARY_HDR (PLOTSETTINGS)
12608 CHECK_DICTIONARY_HDR (PLOTSTYLENAME)
12609 }
12610 if (dwg->header.version >= R_2004)
12611 {
12612 CHECK_DICTIONARY_HDR (MATERIAL)
12613 CHECK_DICTIONARY_HDR (COLOR)
12614 }
12615 if (dwg->header.version >= R_2007)
12616 {
12617 CHECK_DICTIONARY_HDR (VISUALSTYLE)
12618 }
12619 }
12620 #undef CHECK_DICTIONARY_HDR
12621
12622 static void
resolve_postponed_eed_refs(Dwg_Data * restrict dwg)12623 resolve_postponed_eed_refs (Dwg_Data *restrict dwg)
12624 {
12625 LOG_TRACE ("resolve %d postponed eed APPID refs\n", eed_hdls->nitems);
12626 for (uint32_t i = 0; i < eed_hdls->nitems; i++)
12627 {
12628 char *name = eed_hdls->items[i].name;
12629 BITCODE_H ref
12630 = dwg_find_tablehandle (dwg, eed_hdls->items[i].name, "APPID");
12631 if (ref)
12632 {
12633 // copy to eed[i].handle. need: objid + eed[i]
12634 BITCODE_RL objid;
12635 Dwg_Eed *eed;
12636 int j = (int)eed_hdls->items[i].code;
12637 sscanf (eed_hdls->items[i].field, "%d", &objid);
12638 if (objid <= 0 || objid >= dwg->num_objects)
12639 {
12640 LOG_ERROR ("Skip invalid postponed eed APPID %s",
12641 eed_hdls->items[i].field);
12642 continue;
12643 }
12644 eed = dwg->object[objid].tio.object->eed;
12645 if (!eed || j >= (int)dwg->object[objid].tio.object->num_eed)
12646 {
12647 LOG_ERROR ("Skip invalid postponed APPID eed[%d]", j);
12648 continue;
12649 }
12650 memcpy (&eed[j].handle, &ref->handleref, sizeof (Dwg_Handle));
12651 eed[j].handle.code = 5;
12652 LOG_TRACE (
12653 "postponed %s[%d]->eed[%d].handle for APPID.%s => " FORMAT_H
12654 " [H]\n",
12655 dwg->object[objid].name, objid, j, name, ARGS_H (eed[j].handle));
12656 }
12657 else
12658 LOG_WARN ("Unknown eed[].handle for APPID.%s", name)
12659 }
12660 }
12661
12662 EXPORT int
dwg_read_dxf(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12663 dwg_read_dxf (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12664 {
12665 // const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
12666 Dxf_Pair *pair = NULL;
12667 int error = 0;
12668
12669 loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
12670 if (!dat->chain && dat->fh)
12671 {
12672 error = dat_read_stream (dat, dat->fh);
12673 if (error >= DWG_ERR_CRITICAL)
12674 return error;
12675 if (dat->size >= 22 &&
12676 !memcmp (dat->chain, "AutoCAD Binary DXF",
12677 sizeof ("AutoCAD Binary DXF") - 1))
12678 {
12679 dat->opts |= DWG_OPTS_DXFB;
12680 dat->byte = 22;
12681 }
12682 }
12683 if (dat->size < 256)
12684 {
12685 LOG_ERROR ("DXF input too small, %lu byte.\n", dat->size);
12686 return DWG_ERR_IOERROR;
12687 }
12688 /* Fail early on DWG */
12689 if (!memcmp (dat->chain, "AC10", 4) ||
12690 !memcmp (dat->chain, "AC1.", 4) ||
12691 !memcmp (dat->chain, "AC2.10", 4) ||
12692 !memcmp (dat->chain, "MC0.0", 4))
12693 {
12694 LOG_ERROR ("This is a DWG, not a DXF\n");
12695 return DWG_ERR_INVALIDDWG;
12696 }
12697 dat->opts |= DWG_OPTS_INDXF;
12698 dwg->opts |= DWG_OPTS_INDXF;
12699 //num_dxf_objs = 0;
12700 //size_dxf_objs = 1000;
12701 //dxf_objs = (Dxf_Objs *)malloc (1000 * sizeof (Dxf_Objs));
12702 if (!dwg->object_map)
12703 dwg->object_map = hash_new (dat->size / 1000);
12704 // cannot rely on ref->obj during realloc's
12705 dwg->dirty_refs = 1;
12706
12707 header_hdls = new_array_hdls (16);
12708 eed_hdls = new_array_hdls (16);
12709 obj_hdls = new_array_hdls (16);
12710
12711 // start with the BLOCK_HEADER at objid 0
12712 if (!dwg->num_objects)
12713 {
12714 Dwg_Object *obj;
12715 Dwg_Object_BLOCK_HEADER *_obj;
12716 char *dxfname = strdup ((char *)"BLOCK_HEADER");
12717 NEW_OBJECT (dwg, obj);
12718 ADD_OBJECT (BLOCK_HEADER);
12719 // dwg->header.version probably here still unknown. <r2000: 0x17
12720 // later fixed up when reading $ACADVER and the BLOCK_HEADER.name
12721 _obj->name = dwg_add_u8_input (dwg, "*Model_Space");
12722 _obj->is_xref_ref = 1;
12723 obj->tio.object->is_xdic_missing = 1;
12724 dwg_add_handle (&obj->handle, 0, 0x1F, obj);
12725 obj->tio.object->ownerhandle = dwg_add_handleref (dwg, 4, 1, NULL);
12726 }
12727
12728 while (dat->byte < dat->size)
12729 {
12730 pair = dxf_read_pair (dat);
12731 DXF_BREAK_EOF;
12732 pair = dxf_expect_code (dat, pair, 0);
12733 DXF_BREAK_EOF;
12734 if (pair->type == DWG_VT_STRING && strEQc (pair->value.s, "SECTION"))
12735 {
12736 dxf_free_pair (pair);
12737 pair = dxf_read_pair (dat);
12738 DXF_BREAK_EOF;
12739 pair = dxf_expect_code (dat, pair, 2);
12740 DXF_BREAK_EOF;
12741 if (!pair->value.s)
12742 {
12743 LOG_ERROR ("Expected SECTION string code 2, got code %d",
12744 pair->code);
12745 dxf_free_pair (pair);
12746 pair = NULL;
12747 break;
12748 }
12749 else if (strEQc (pair->value.s, "HEADER"))
12750 {
12751 dxf_free_pair (pair);
12752 pair = NULL;
12753 error = dxf_header_read (dat, dwg);
12754 if (error > DWG_ERR_CRITICAL)
12755 goto error;
12756 dxf_fixup_header (dwg);
12757 // skip minimal DXF
12758 /*
12759 if (!dwg->header_vars.DIMPOST) // T in all versions
12760 {
12761 LOG_ERROR ("Unsupported minimal DXF");
12762 return DWG_ERR_INVALIDDWG;
12763 }
12764 */
12765 }
12766 else if (strEQc (pair->value.s, "CLASSES"))
12767 {
12768 dxf_free_pair (pair);
12769 pair = NULL;
12770 error = dxf_classes_read (dat, dwg);
12771 if (error > DWG_ERR_CRITICAL)
12772 return error;
12773 }
12774 else if (strEQc (pair->value.s, "TABLES"))
12775 {
12776 BITCODE_H hdl;
12777 dxf_free_pair (pair);
12778 pair = NULL;
12779 error = dxf_tables_read (dat, dwg);
12780 if (error > DWG_ERR_CRITICAL)
12781 goto error;
12782
12783 resolve_postponed_header_refs (dwg);
12784 resolve_postponed_eed_refs (dwg);
12785
12786 // should not happen
12787 if (!dwg->header_vars.LTYPE_BYLAYER
12788 && (hdl = dwg_find_tablehandle_silent (
12789 dwg, (char *)"ByLayer", "LTYPE")))
12790 dwg->header_vars.LTYPE_BYLAYER
12791 = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12792 // should not happen
12793 if (!dwg->header_vars.LTYPE_BYBLOCK
12794 && (hdl = dwg_find_tablehandle_silent (
12795 dwg, (char *)"ByBlock", "LTYPE")))
12796 dwg->header_vars.LTYPE_BYBLOCK
12797 = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12798 // but this is needed
12799 if (!dwg->header_vars.LTYPE_CONTINUOUS
12800 && (hdl = dwg_find_tablehandle_silent (
12801 dwg, (char *)"Continuous", "LTYPE")))
12802 dwg->header_vars.LTYPE_CONTINUOUS
12803 = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12804 }
12805 else if (strEQc (pair->value.s, "BLOCKS"))
12806 {
12807 BITCODE_H hdl;
12808 dxf_free_pair (pair);
12809 pair = NULL;
12810 error = dxf_blocks_read (dat, dwg);
12811 if (error > DWG_ERR_CRITICAL)
12812 goto error;
12813
12814 // resolve_postponed_header_refs (dwg);
12815 if (!dwg->header_vars.BLOCK_RECORD_PSPACE
12816 && (hdl = dwg_find_tablehandle_silent (
12817 dwg, (char *)"*Paper_Space", "BLOCK")))
12818 dwg->header_vars.BLOCK_RECORD_PSPACE
12819 = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12820 if (!dwg->header_vars.BLOCK_RECORD_MSPACE
12821 && (hdl = dwg_find_tablehandle_silent (
12822 dwg, (char *)"*Model_Space", "BLOCK")))
12823 dwg->header_vars.BLOCK_RECORD_MSPACE
12824 = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12825 }
12826 else if (strEQc (pair->value.s, "ENTITIES"))
12827 {
12828 dxf_free_pair (pair);
12829 pair = NULL;
12830 error = dxf_entities_read (dat, dwg);
12831 if (error > DWG_ERR_CRITICAL)
12832 goto error;
12833 }
12834 else if (strEQc (pair->value.s, "OBJECTS"))
12835 {
12836 dxf_free_pair (pair);
12837 pair = NULL;
12838 error = dxf_objects_read (dat, dwg);
12839 if (error > DWG_ERR_CRITICAL)
12840 goto error;
12841 resolve_header_dicts (dwg);
12842 }
12843 else if (strEQc (pair->value.s, "THUMBNAILIMAGE"))
12844 {
12845 dxf_free_pair (pair);
12846 pair = NULL;
12847 error = dxf_thumbnail_read (dat, dwg);
12848 }
12849 else if (strEQc (pair->value.s, "ACDSDATA"))
12850 {
12851 dxf_free_pair (pair);
12852 pair = NULL;
12853 error = dxf_acds_read (dat, dwg);
12854 }
12855 else // if (strEQc (pair->value.s, ""))
12856 {
12857 LOG_WARN ("SECTION %s ignored for now", pair->value.s);
12858 dxf_free_pair (pair);
12859 pair = NULL;
12860 error = dxf_unknownsection_read (dat, dwg);
12861 }
12862 }
12863 else
12864 {
12865 LOG_ERROR ("Expected string SECTION");
12866 dxf_free_pair (pair);
12867 }
12868 }
12869 if (pair != NULL && pair->code == 0 &&
12870 pair->value.s != NULL && strEQc (pair->value.s, "EOF"))
12871 ;
12872 else if (dat->byte >= dat->size || (pair == NULL))
12873 error |= DWG_ERR_IOERROR;
12874 resolve_postponed_header_refs (dwg);
12875 resolve_postponed_object_refs (dwg);
12876 LOG_HANDLE ("Resolving pointers from ObjectRef vector:\n");
12877 dwg_resolve_objectrefs_silent (dwg);
12878 free_array_hdls (header_hdls);
12879 free_array_hdls (eed_hdls);
12880 free_array_hdls (obj_hdls);
12881 if (dwg->header.version <= R_2000 && dwg->header.from_version > R_2000)
12882 dwg_fixup_BLOCKS_entities (dwg);
12883 LOG_TRACE ("import from DXF\n");
12884 if (error > DWG_ERR_CRITICAL)
12885 return error;
12886 else
12887 return dwg->num_objects ? 1 : 0;
12888
12889 error:
12890 dwg->dirty_refs = 0;
12891 free_array_hdls (header_hdls);
12892 free_array_hdls (eed_hdls);
12893 free_array_hdls (obj_hdls);
12894 return error;
12895 }
12896
12897 EXPORT int
dwg_read_dxfb(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12898 dwg_read_dxfb (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12899 {
12900 dwg->opts |= DWG_OPTS_DXFB; // binary
12901 dat->opts |= DWG_OPTS_DXFB;
12902 if (dat->size >= 22 && dat->byte < 22 &&
12903 !memcmp (dat->chain, "AutoCAD Binary DXF",
12904 sizeof ("AutoCAD Binary DXF") - 1))
12905 {
12906 dat->byte = 22;
12907 }
12908 return dwg_read_dxf (dat, dwg);
12909 }
12910
12911 #undef IS_INDXF
12912