From 76afd7eabb9d87e840075bca2d1e3772258270b5 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Sat, 17 Oct 2026 20:08:47 +0300 Subject: [PATCH] XCLIP: a copy taken before the clip was set still finds its filter insert_spatial_filter reads the INSERT's own dictionary link since 3a3d2e4a8; a caller holding a copy made before XCLIP linked the dictionary saw none. Fall back to the stored INSERT's link, still O(1). Co-Authored-By: Claude Opus 5.5 --- src/scene/pick/xclip.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/scene/pick/xclip.rs b/src/scene/pick/xclip.rs index 1c823eb23..c706935ec 100644 --- a/src/scene/pick/xclip.rs +++ b/src/scene/pick/xclip.rs @@ -48,12 +48,20 @@ fn resolve_extension_dictionary(doc: &CadDocument, owner: Handle) -> Option Option { - ins.common.xdictionary_handle.filter(|h| !h.is_null()) +/// The INSERT's extension dictionary through its own link, or the stored +/// INSERT's when `ins` is a copy taken before the link was made. Render walks +/// ask this for every INSERT, so it must not fall back to a scan of every +/// object: [`CadDocument::extension_dictionary_handle`] scans for an entity +/// without a linked dictionary. Readers and `ensure_extension_dictionary` +/// set the link. +fn linked_extension_dictionary(doc: &CadDocument, ins: &Insert) -> Option { + ins.common + .xdictionary_handle + .or_else(|| { + doc.get_entity(ins.common.handle) + .and_then(|stored| stored.common().xdictionary_handle) + }) + .filter(|h| !h.is_null()) } /// Resolve the enabled XCLIP spatial filter for `ins`, if any. @@ -63,7 +71,7 @@ fn linked_extension_dictionary(ins: &Insert) -> Option { /// filter, it is disabled (code 71 = 0), or it has fewer than two boundary /// points. pub fn insert_spatial_filter<'a>(doc: &'a CadDocument, ins: &Insert) -> Option<&'a SpatialFilter> { - let xdict = linked_extension_dictionary(ins)?; + let xdict = linked_extension_dictionary(doc, ins)?; let acad_filter = dict_entry(doc, xdict, "ACAD_FILTER")?; let spatial = dict_entry(doc, acad_filter, "SPATIAL")?; match doc.objects.get(&spatial)? { @@ -81,7 +89,7 @@ pub fn filter_handle(doc: &CadDocument, insert: Handle) -> Option { let Some(codec::EntityType::Insert(ins)) = doc.get_entity(insert) else { return None; }; - let xdict = linked_extension_dictionary(ins)?; + let xdict = linked_extension_dictionary(doc, ins)?; let acad_filter = dict_entry(doc, xdict, "ACAD_FILTER")?; let spatial = dict_entry(doc, acad_filter, "SPATIAL")?; matches!(