From 7c75779fc823e113dcf3a604aa6f01b9b22f1933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Josef=20=C5=A0pa=C4=8Dek?= Date: Mon, 29 Jan 2024 16:44:12 +0100 Subject: [PATCH] Split objfreespace and second header --- include/dwg.h | 5 +++-- src/decode.c | 1 - src/dwg.c | 36 +++++++++++++++++++------------- src/encode.c | 58 +++++++++++++++++++++++++++++++-------------------- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/include/dwg.h b/include/dwg.h index a2d8001ebd..d66bc3bb41 100644 --- a/include/dwg.h +++ b/include/dwg.h @@ -9054,10 +9054,11 @@ typedef enum DWG_SECTION_TYPE_R13 SECTION_HEADER_R13 = 0, SECTION_CLASSES_R13 = 1, SECTION_HANDLES_R13 = 2, - SECTION_OBJFREESPACE_R13 = 3, /* including the 2ndheader */ + SECTION_OBJFREESPACE_R13 = 3, SECTION_TEMPLATE_R13 = 4, SECTION_AUXHEADER_R2000 = 5, SECTION_THUMBNAIL_R13 = 6, + SECTION_SECOND_HEADER_R13 = 7, } Dwg_Section_Type_r13; typedef enum DWG_SECTION_TYPE_R11 /* tables */ @@ -9396,7 +9397,7 @@ typedef struct _dwg_header BITCODE_RL summaryinfo_address; /* R2004+ */ BITCODE_RL vbaproj_address; /* R2004+ */ BITCODE_RL r2004_header_address; /* R2004+ */ - BITCODE_RL sections; // as in the header, 5 or 6 usually + BITCODE_RL sections; // as in the header, 3 .. 6 usually BITCODE_RL num_sections; // as allocated, many more Dwg_Section *section; Dwg_Section_InfoHdr section_infohdr; /* R2004+ */ diff --git a/src/decode.c b/src/decode.c index 4c5aa4df42..561ce761c5 100644 --- a/src/decode.c +++ b/src/decode.c @@ -333,7 +333,6 @@ decode_R13_R2000 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) * 1: class section * 2: Handles (object map) * 3: optional: ObjFreeSpace - * -: 2ndHeader and its sentinels * 4: optional: Template (MEASUREMENT) * 5: optional: AuxHeader (no sentinels, since R13c3) */ diff --git a/src/dwg.c b/src/dwg.c index cc8f3971b6..341a6fb5d7 100644 --- a/src/dwg.c +++ b/src/dwg.c @@ -3473,7 +3473,8 @@ dwg_sections_init (Dwg_Data *dwg) /* section 0: header vars * 1: class section * 2: object map (i.e. handles) - * 3: optional ObjFreeSpace (r13+, no sentinels) + 2ndheader (r13+, sentinels) + * 3: optional ObjFreeSpace (r13c3+, no sentinels) + * 7: 2ndheader (not a section, r13+, sentinels) * 4: optional: Template (MEASUREMENT) * 5: optional: AuxHeader (no sentinels, since R_2000b) * 6: optional: THUMBNAIL (not a section, but treated as one) @@ -3481,22 +3482,27 @@ dwg_sections_init (Dwg_Data *dwg) if (!dwg->header.num_sections || (dwg->header.from_version > R_2000 && dwg->header.version <= R_2000)) { - dwg->header.num_sections = dwg->header.version < R_13c3 ? 3 - : dwg->header.version < R_2000b ? 5 - : 6; - if (dwg->header.num_sections == 3 && dwg->objfreespace.numnums) - dwg->header.num_sections = 5; + if (dwg->header.sections) + { + // Plus thumbnail and second header + dwg->header.num_sections = dwg->header.sections + 2; + } + else + { + dwg->header.num_sections = dwg->header.version < R_13c3 ? 5 + : dwg->header.version < R_2000b ? 7 + : 8; + if (dwg->header.num_sections == 5 && dwg->objfreespace.numnums) + dwg->header.num_sections = 6; + } } if (!dwg->header.sections || (dwg->header.from_version > R_2000 && dwg->header.version <= R_2000)) - // ODA writes zeros - dwg->header.sections = dwg->header.num_sections; - // newer DWG's have proper HEADER.sections - if (dwg->header.num_sections != dwg->header.sections) - dwg->header.num_sections = dwg->header.sections; + // ODA writes zeros + dwg->header.sections = dwg->header.num_sections - 2; } LOG_TRACE ("num_sections => " FORMAT_RL "\n", dwg->header.num_sections); - if (dwg->header.num_sections < 3) + if (dwg->header.num_sections < 5) { LOG_ERROR ("Not enough sections: " FORMAT_RL, dwg->header.num_sections); return DWG_ERR_INVALIDDWG; @@ -3508,12 +3514,12 @@ dwg_sections_init (Dwg_Data *dwg) } if (dwg->header.section) - // zero-based, including THUMBNAIL + // zero-based, including THUMBNAIL and Second Header dwg->header.section = (Dwg_Section *)realloc ( dwg->header.section, - sizeof (Dwg_Section) * (dwg->header.num_sections + 2)); + sizeof (Dwg_Section) * (dwg->header.num_sections)); else - dwg->header.section = (Dwg_Section *)calloc (dwg->header.num_sections + 2, + dwg->header.section = (Dwg_Section *)calloc (dwg->header.num_sections, sizeof (Dwg_Section)); if (!dwg->header.section) { diff --git a/src/encode.c b/src/encode.c index f5c98f2946..73f4890af9 100644 --- a/src/encode.c +++ b/src/encode.c @@ -87,7 +87,7 @@ static BITCODE_BL rcount1 = 0, rcount2 = 0; /* section_order: A static array of section types. SECTION_R13_SIZE is the size and the sentinel. */ -#define SECTION_R13_SIZE 7U +#define SECTION_R13_SIZE 8U static Dwg_Section_Type_r13 section_order[SECTION_R13_SIZE] = { 0 }; #ifdef USE_TRACING @@ -1998,7 +1998,7 @@ find_section_info_type (const Dwg_Data *restrict dwg, Dwg_Section_Type type) return NULL; } -/* Ordering of r13-r2000 sections 0-6 */ +/* Ordering of r13-r2000 sections 0-7 */ static void section_order_trace (const Dwg_Data *dwg, const BITCODE_BL numsections, @@ -3080,13 +3080,12 @@ encode_objects_handles (Dwg_Data *restrict dwg, Bit_Chain *restrict dat, } static int -encode_objfreespace_2ndheader (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) +encode_objfreespace (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) { int error = 0; /*------------------------------------------------------------ - * ObjFreeSpace and Second header - r13-r2000 only. - * Note: partially also since r2004. + * ObjFreeSpace - r13c3-r2000 only. */ if (dwg->header.version >= R_13 && dwg->header.version < R_2004 && dwg->header.num_sections > 3) @@ -3105,8 +3104,18 @@ encode_objfreespace_2ndheader (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) } } - if (dwg->header.version >= R_13 && dwg->header.version < R_2004 && - dwg->secondheader.codepage) + return error; +} + +static int +encode_2ndheader (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) +{ + int error = 0; + + /*------------------------------------------------------------ + * Second Header - r13-r2000 only. + */ + if (dwg->header.version >= R_13 && dwg->header.version < R_2004) { struct _dwg_secondheader *_obj = &dwg->secondheader; Dwg_Object *obj = NULL; @@ -3733,15 +3742,15 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) THUMBNAIL * 2: Handles * 3: ObjFreeSpace (r13c3+, optional) - + 2NDHEADER (r13-r2000) + * 7: 2NDHEADER (r13-r2000, not a section) * 4: Template (r14-r2000, optional) * 5: AuxHeader (r2000, no sentinels) * 6: THUMBNAIL (r13c3+, not a section) */ - /* Usually 3-5, max 6 */ + /* Usually 5-7, max 8 */ if (!dwg->header.num_sections - || (dat->from_version >= R_2004 && dwg->header.num_sections > 6)) + || (dat->from_version >= R_2004 && dwg->header.num_sections > 8)) { if (dwg->header.version <= R_2000) { @@ -3750,11 +3759,11 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) else dwg->header.num_sections = dwg->auxheader.dwg_version && dwg->header.version == R_2000 - ? 6 - : 5; + ? 7 + : 6; } else - dwg->header.num_sections = 6; + dwg->header.num_sections = 7; // minimal DXF: // if (dwg->opts & (DWG_OPTS_INDXF | DWG_OPTS_MINIMAL) // && (!dwg->header_vars.HANDSEED || @@ -3784,19 +3793,23 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) if (dwg->header.sections > 3) { section_order[3] = SECTION_OBJFREESPACE_R13; - section_order[4] = SECTION_TEMPLATE_R13; + section_order[4] = SECTION_SECOND_HEADER_R13; + section_order[5] = SECTION_TEMPLATE_R13; if (dwg->header.sections > 5) { - section_order[5] = SECTION_AUXHEADER_R2000; - section_order[6] = SECTION_THUMBNAIL_R13; + section_order[6] = SECTION_AUXHEADER_R2000; + section_order[7] = SECTION_THUMBNAIL_R13; } else { - section_order[5] = SECTION_THUMBNAIL_R13; + section_order[6] = SECTION_THUMBNAIL_R13; } } else - section_order[3] = SECTION_THUMBNAIL_R13; + { + section_order[3] = SECTION_THUMBNAIL_R13; + section_order[4] = SECTION_SECOND_HEADER_R13; + } if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE) section_order_trace (dwg, dwg->header.num_sections, @@ -3915,7 +3928,10 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) error |= encode_objects_handles (dwg, dat, (Bit_Chain **)&sec_dat); break; case SECTION_OBJFREESPACE_R13: - error |= encode_objfreespace_2ndheader (dwg, dat); + error |= encode_objfreespace (dwg, dat); + break; + case SECTION_SECOND_HEADER_R13: + error |= encode_2ndheader (dwg, dat); break; case SECTION_TEMPLATE_R13: error |= encode_template (dwg, dat); @@ -3932,10 +3948,6 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) } } } - if (dwg->header.sections == 3 && dwg->secondheader.codepage) - { - error |= encode_objfreespace_2ndheader (dwg, dat); - } } // VERSIONS (R_13b1, R_2004) VERSIONS (R_2007a, R_2007)