Write BlockRepresentationData (AcDbRepData) in DWG and DXF#1137
Write BlockRepresentationData (AcDbRepData) in DWG and DXF#1137Sipowiz wants to merge 5 commits into
Conversation
DxfObjectsSectionWriter.writeDictionary emitted the 3/350 entry pair for every dictionary entry, while writeObject later dropped the unsupported types via isObjectSupported. The output contained soft-ownership handles pointing to objects that were never written (e.g. ACAD_ENHANCEDBLOCK, AcDbRepData, visual styles), which readers report as missing entries. Filter the entries with isObjectSupported before writing the pair and enqueuing the object, mirroring the skipEntry filtering already done by the dwg writer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An object can be enqueued in the objects section queue multiple times, once by the dictionary that owns it and once by the objects that reference it, e.g. a Field enqueued by its owning dictionary and by the FieldList that references it. Each copy was written to the output, and reading the result back created duplicated templates whose builds assigned the same object to two owners, failing with 'Item already has an owner'. Track the written handles and write each object only once. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Writing a document containing a Field whose value string is null failed with a NullReferenceException in writeLongTextValue. Treat the null text as an empty string, matching the dwg writer behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Split the per-parameter assert helpers into assertRepresentationChain (the per-insert AcDbBlockRepresentation -> AcDbRepData + AppDataCache -> ACAD_ENHANCEDBLOCKDATA chain) and assertGraph<T> (the evaluation graph node expressions), dispatched by assertIsolatedDocument. This allows the write round-trip tests to assert the representation chain independently from the evaluation graph, which is not written yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove BlockRepresentationData from the writer skip lists and emit the object mirroring the readers: BS 70 followed by a hard pointer (340) to the source block record. The per-insert representation chain (AcDbBlockRepresentation -> AcDbRepData) is restored on the output while the evaluation graph is still dropped, so dynamic block inserts keep the link to their source block record. Add the AcDbBlockRepresentationData class to UpdateDxfClasses with the values found in AutoCAD generated files (proxy flags 1153, maintenance version 58) so documents created from scratch get a valid CLASSES entry. Add write and re-read round-trip tests over the dynamic-blocks samples for both formats, asserting the representation chain and the absence of dangling dictionary handles. The tests run unconditionally so they are not skipped in CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
It seems that there is a duplication of the task done in: |
|
Sorry for the confusion — #1137 is stacked on top of #1136, so its branch currently contains #1136's three commits as well; that's the overlap you're seeing, not a re-do. Its own change is a single commit: the Once #1136 merges I'll rebase this onto master so the diff shows only the RepData writer. Want me to rebase now onto #1136's branch instead, or hold until #1136 lands? (I'll also drop the |
|
Hi @Sipowiz, I've been working on the dynamic parameters and I managed to implement the first successful result for the DxfWriter: I think this one can be closed. |
First step toward the dynamic-block write support discussed in #1133: writing
BlockRepresentationData(AcDbRepData) in both the DWG and DXF writers.What this does
BlockRepresentationDatais the per-insert object (underInsert.XDictionary → AcDbBlockRepresentation → AcDbRepData) that links an anonymous*U…block instance back to its source dynamic block. Its siblingAppDataCache → ACAD_ENHANCEDBLOCKDATA → XRecordchain already round-trips through the existing dictionary/XRecord writers — onlyAcDbRepDataitself was dropped byskipEntry/isObjectSupported.BlockRepresentationDatafrom the DWGskipEntryand DXFisObjectSupporteddrop-lists.writeBlockRepresentationDatain both writers, mirroring the readers:BS 70(Value70) + a hard pointer (340) to the sourceBlockRecord.AcDbBlockRepresentationDataDxfClassentry (values taken from AutoCAD-authored files:ProxyFlags=1153,ItemClassId=499,DwgVersion=AC1018,MaintenanceVersion=58; identical across the AC1027 and AC1032 files I checked).DynamicBlockTestsasserts into a reusableassertRepresentationChainlayer and adds unconditional DWG + DXF round-trip theories (they are not gated onSELF_CHECK_OUTPUT, so they run in CI).Scope / what this deliberately does NOT do
This does not write the
EvaluationGraph(ACAD_ENHANCEDBLOCK) — you mentioned in #1133 you're exploring that yourself, so I've kept this PR to the representation-data half and left the graph alone.Validation against real AutoCAD
I ran the rewritten files through AutoCAD 2022 (via COM
AUDIT+ block-reference enumeration) on a corpus of real production dynamic-block templates: all open without a recover prompt and audit-clean apart from a finding that is already present in the untouched source file (an unrelatedACAD_LAYERFILTERSXRecord length). One honest caveat: restoringAcDbRepDataalone does not makeIsDynamicBlockreturn true — that needs the graph — but it adds no audit errors and is a prerequisite for it. 61/61DynamicBlockTestspass.Note
Stacked on #1136 (the DXF objects-section writer fixes) — the round-trip tests here rely on those. I'll rebase once #1136 merges; until then this branch contains those three commits too.