From a4698c5b6b3fcfa251b8072650e6bbe05aabce26 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Sat, 8 Aug 2026 00:11:57 +0300 Subject: [PATCH] fix(units): leave the sheet viewport alone when converting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DWGUNITS reframed every viewport by the conversion factor, on the reasoning that a viewport's framing is measured in model units and has to follow them. That holds for a window onto the model; it does not hold for a layout's sheet viewport, whose view is the paper itself, in paper units. Scaling it left the sheet the size it was while the view of it moved by a thousand. Only a paper-space viewport can be a sheet — the model-space scale reached everything else, and what it reached frames the model by definition. Among the rest, the layout names its sheet outright, and a file arriving without that link still gives itself away by sitting at the paper origin, where only the sheet sits. Co-Authored-By: Claude Opus 5 --- src/app/commands/layers.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/app/commands/layers.rs b/src/app/commands/layers.rs index 29296ce65..c695036e1 100644 --- a/src/app/commands/layers.rs +++ b/src/app/commands/layers.rs @@ -833,6 +833,21 @@ impl OpenCADStudio { // `transform_viewport` covers the rectangle and the target but not the // framing, so the framing is done here for every viewport, and the // target only for the ones the scale above did not already reach. + // Not every viewport frames the model, though. Each layout's sheet + // viewport frames the sheet — its view is the paper, measured in paper + // units — so scaling it by the model's factor would leave the drawing + // frame the same size as before while the view of it changed by a + // thousand, which is the boundary appearing to break. + let sheets: std::collections::HashSet = self.tabs[i] + .scene + .document + .objects + .values() + .filter_map(|object| match object { + acadrust::objects::ObjectType::Layout(layout) => Some(layout.viewport), + _ => None, + }) + .collect(); let scaled: std::collections::HashSet = handles.iter().copied().collect(); let mut reframed = 0usize; for entity in self.tabs[i].scene.document.entities_mut() { @@ -840,6 +855,17 @@ impl OpenCADStudio { let acadrust::entities::EntityType::Viewport(vp) = entity else { continue; }; + // Only a paper-space viewport can be a sheet — the scale above + // reached everything in model space, and what it reached frames the + // model by definition. Among the rest, the layout names its sheet + // outright, and a file that arrives without that link still gives + // itself away by sitting at the paper origin, where only the sheet + // sits. + let is_sheet = !scaled.contains(&handle) + && (sheets.contains(&handle) || !crate::scene::Scene::is_content_viewport(vp)); + if is_sheet { + continue; + } vp.view_center = vp.view_center * factor; vp.view_height *= factor; if vp.custom_scale.abs() > 1e-12 {