diff --git a/Cargo.lock b/Cargo.lock index fc76e9b93..662daabef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2397,7 +2397,7 @@ dependencies = [ "hayro-syntax", "kurbo 0.13.1", "moxcms", - "phf", + "phf 0.13.1", "rustc-hash 2.1.3", "siphasher", "skrifa 0.42.1", @@ -4348,6 +4348,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "oem_cp" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7959d3349f484aec36462f98226983578bf7d33f9b034c32967489c7000e1f" +dependencies = [ + "phf 0.11.3", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -4373,7 +4382,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/ramox81/cadcodec.git?rev=6434df7#6434df7049b4b81e66b8884180587efda343e070" +source = "git+https://github.com/ramox81/cadcodec.git?rev=67d53cb#67d53cb769d0db90302c24113553d87f8a997fee" dependencies = [ "anyhow", "bitflags 2.13.1", @@ -4385,6 +4394,7 @@ dependencies = [ "itoa", "memmap2", "nom 7.1.3", + "oem_cp", "once_cell", "rayon", "ryu", @@ -4396,7 +4406,7 @@ dependencies = [ [[package]] name = "opencadgraph" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=88cdae0#88cdae06858f6811f5058a5686bc1edb5ff39910" +source = "git+https://github.com/HakanSeven12/opencadgraph.git?rev=5d4e713#5d4e713968bd515be15302079d9edc1fd3df4df0" dependencies = [ "opencadkernel", "serde_json", @@ -4405,7 +4415,7 @@ dependencies = [ [[package]] name = "opencadkernel" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=5811296#5811296a6c98ea9b12defa977f08d74cfc739014" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=dfca391#dfca3912228b19d4df25c8695b628ccb13497a78" dependencies = [ "cavalier_contours", "opencadcodec", @@ -4416,7 +4426,7 @@ dependencies = [ [[package]] name = "opencadkernel-constraints" version = "0.1.0" -source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=5811296#5811296a6c98ea9b12defa977f08d74cfc739014" +source = "git+https://github.com/HakanSeven12/opencadkernel.git?rev=dfca391#dfca3912228b19d4df25c8695b628ccb13497a78" dependencies = [ "nalgebra", ] @@ -4595,6 +4605,15 @@ dependencies = [ "indexmap", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] + [[package]] name = "phf" version = "0.13.1" @@ -4602,7 +4621,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ "phf_macros", - "phf_shared", + "phf_shared 0.13.1", ] [[package]] @@ -4612,7 +4631,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ "fastrand", - "phf_shared", + "phf_shared 0.13.1", ] [[package]] @@ -4622,12 +4641,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ "phf_generator", - "phf_shared", + "phf_shared 0.13.1", "proc-macro2", "quote", "syn 2.0.119", ] +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "phf_shared" version = "0.13.1" diff --git a/Cargo.toml b/Cargo.toml index f05bd0dd1..cca1688df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,10 +37,10 @@ rfd = "0.17" clap = { version = "4", features = ["derive", "string"] } env_logger = "0.11" log = "0.4" -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } -kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "5811296", features = ["acis", "offset"] } -kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "5811296" } -graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "88cdae0" } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "325fa98", features = ["serde"] } +kernel = { package = "opencadkernel", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "dfca391", features = ["acis", "offset"] } +kernel-constraints = { package = "opencadkernel-constraints", git = "https://github.com/HakanSeven12/opencadkernel.git", rev = "dfca391" } +graph = { package = "opencadgraph", git = "https://github.com/HakanSeven12/opencadgraph.git", rev = "5d4e713" } dwg-thumbnailer = { path = "crates/dwg-thumbnailer" } # Shared SAVE serialization dispatch + web-worker wire format: one # implementation for the inline (fallback/native) path and the worker path. @@ -224,4 +224,4 @@ name = "integration" path = "tests/integration.rs" [patch."https://github.com/HakanSeven12/opencadcodec.git"] -opencadcodec = { git = "https://github.com/ramox81/cadcodec.git", rev = "6434df7" } +opencadcodec = { git = "https://github.com/ramox81/cadcodec.git", rev = "67d53cb" } diff --git a/benches/command_benchmarks.rs b/benches/command_benchmarks.rs index c65439c4a..8e90a5c00 100644 --- a/benches/command_benchmarks.rs +++ b/benches/command_benchmarks.rs @@ -101,7 +101,7 @@ fn push_fixture_entities(doc: &mut CadDocument, quick: bool) -> Vec { d.definition_point = Vector3::new(x + 5.0, y + 3.0, 0.0); d.base.text_middle_point = Vector3::new(x + 5.0, y + 4.0, 0.0); handles.push( - doc.add_entity(EntityType::Dimension(Dimension::Linear(d))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(), ); } diff --git a/crates/ocs_plugin_api/Cargo.toml b/crates/ocs_plugin_api/Cargo.toml index 6a528cac8..dc495b6eb 100644 --- a/crates/ocs_plugin_api/Cargo.toml +++ b/crates/ocs_plugin_api/Cargo.toml @@ -15,7 +15,7 @@ serde_json = { version = "1", optional = true } # Pulled in only by the `host` feature, which adds the `opencadcodec`-typed # `HostApi` runtime surface. The default crate stays dependency-free so engine # crates and external tooling can depend on the manifest/ribbon contract cheaply. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", optional = true, features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "325fa98", optional = true, features = ["serde"] } # Runtime IPC and serialization (host feature only). interprocess = { version = "2", optional = true } @@ -39,7 +39,7 @@ serde_json = "1" serde = { version = "1", features = ["derive"] } cargo-lock = "11" # opencadcodec is scanned at build time to generate the embedded type registry. -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "325fa98", features = ["serde"] } [dev-dependencies] serde_json = "1" diff --git a/crates/ocs_plugin_api/src/entity_coverage.rs b/crates/ocs_plugin_api/src/entity_coverage.rs index aa2901297..c723c1266 100644 --- a/crates/ocs_plugin_api/src/entity_coverage.rs +++ b/crates/ocs_plugin_api/src/entity_coverage.rs @@ -3583,7 +3583,7 @@ mod tests { #[test] fn unsupported_canvas_kind_has_typed_snapshot_fields() { use crate::host::codec; - let hatch = codec::EntityType::Hatch(codec::entities::Hatch::default()); + let hatch = codec::EntityType::Hatch(Box::new(codec::entities::Hatch::default())); let snapshot = entity_snapshot(&hatch).unwrap(); let fields = snapshot .get("Hatch") @@ -3713,7 +3713,7 @@ mod tests { #[test] fn canvas_layer_patch_preserves_unmapped_hatch_fields() { use crate::host::codec; - let hatch = codec::EntityType::Hatch(codec::entities::Hatch::default()); + let hatch = codec::EntityType::Hatch(Box::new(codec::entities::Hatch::default())); let patched = patch_canvas_layer(&hatch, "HATCHES").unwrap(); assert_eq!(patched.common().layer, "HATCHES"); assert_eq!(hatch.common().layer, "0"); @@ -3809,13 +3809,13 @@ mod tests { })); } hatch.paths.push(path); - let entity = codec::EntityType::Hatch(hatch.clone()); + let entity = codec::EntityType::Hatch(Box::new(hatch.clone())); validate_new_canvas_entity(&entity).unwrap(); let mut invalid = hatch.clone(); invalid.paths.clear(); assert!( - validate_new_canvas_entity(&codec::EntityType::Hatch(invalid)) + validate_new_canvas_entity(&codec::EntityType::Hatch(Box::new(invalid))) .unwrap_err() .contains("at least one boundary path") ); @@ -3824,7 +3824,7 @@ mod tests { invalid.is_solid = false; invalid.pattern_scale = 0.0; assert!( - validate_new_canvas_entity(&codec::EntityType::Hatch(invalid)) + validate_new_canvas_entity(&codec::EntityType::Hatch(Box::new(invalid))) .unwrap_err() .contains("greater than zero") ); @@ -3841,13 +3841,13 @@ mod tests { associative.paths[0].boundary_handles.push(boundary); validate_canvas_entity_references( &document, - &codec::EntityType::Hatch(associative.clone()), + &codec::EntityType::Hatch(Box::new(associative.clone())), ) .unwrap(); associative.paths[0].boundary_handles[0] = codec::Handle::new(u64::MAX); assert!(validate_canvas_entity_references( &document, - &codec::EntityType::Hatch(associative), + &codec::EntityType::Hatch(Box::new(associative)), ) .unwrap_err() .contains("does not exist")); diff --git a/crates/ocs_save/Cargo.toml b/crates/ocs_save/Cargo.toml index 687cbe234..a64f550ef 100644 --- a/crates/ocs_save/Cargo.toml +++ b/crates/ocs_save/Cargo.toml @@ -10,6 +10,6 @@ publish = false # exactly one implementation. No UI/app dependencies — only the codec + serde. [dependencies] -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "325fa98", features = ["serde"] } bincode = "1.3" serde = { version = "1", features = ["derive"] } diff --git a/crates/ocs_web_worker/Cargo.toml b/crates/ocs_web_worker/Cargo.toml index 656935b3c..bc91d4438 100644 --- a/crates/ocs_web_worker/Cargo.toml +++ b/crates/ocs_web_worker/Cargo.toml @@ -8,7 +8,7 @@ publish = false crate-type = ["cdylib"] [dependencies] -codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c", features = ["serde"] } +codec = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "325fa98", features = ["serde"] } bincode = "1.3" serde = { version = "1", features = ["derive"] } console_error_panic_hook = "0.1" diff --git a/docs/plugin-template-v2/Cargo.toml b/docs/plugin-template-v2/Cargo.toml index 484fad237..63a19d6b5 100644 --- a/docs/plugin-template-v2/Cargo.toml +++ b/docs/plugin-template-v2/Cargo.toml @@ -16,4 +16,4 @@ ocs_plugin_api = { path = "../../crates/ocs_plugin_api", features = ["host"] } # entry): the plugin's entities and the host's re-exports are the same types # only when both resolve the same revision. The registration `rustc` / # `acadrust_source` gates enforce this at load time too. -acadrust = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "102f04c" } +acadrust = { package = "opencadcodec", git = "https://github.com/HakanSeven12/opencadcodec.git", rev = "325fa98" } diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 7e3d4df3a..e13af8f47 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = تعذر على الاسترداد إنتاج بيانات رسم قابلة للاستخدام. راجع التقرير وجرّب نسخة احتياطية أو نسخة حفظ تلقائي. .entities-checked = الكيانات التي تم فحصها .issues-found = المشكلات الموجودة - .entities-removed = الكيانات التي تمت إزالتها .references-checked = المراجع التي تم فحصها - .referenced-entities-removed = الكيانات المرجعية التي تمت إزالتها .references-unavailable = المراجع غير المتاحة .log-path = سجل الاسترداد .log-write-failed = تعذرت كتابة سجل الاسترداد @@ -2603,8 +2601,6 @@ file = .usage-undo-number-of-steps = الاستخدام: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = يُستخدم للحفظ الأول لرسم جديد. تحتفظ الرسومات الحالية بنوع ملفها وإصدارها. .visual-style-label = النمط المرئي: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = تحذير: أُسقط __ocs_fmt_0__ كيان تالف (بيانات تحليل غير صالحة — اتجاهات/أعداد سيئة) - .warning-corrupt-xref-entities-dropped = تحذير: أُسقط __ocs_fmt_0__ كيان مرجع خارجي تالف .xref-loaded = XREF حُمّل "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: لا يمكن إنشاء ZIP الإرسال (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: تعذر إنشاء المجلد (__ocs_fmt_1__). @@ -5650,9 +5646,9 @@ styles = .aci-color-index = فهرس ألوان ACI .aci = ACI: .audit-no-issues-found = AUDIT: لم يُعثر على مشكلات. - .audit-reference-s-to-undefined-block-s = AUDIT: مراجع إلى كتل غير معرّفة: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: مراجع إلى طبقات غير معرّفة: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: تقرير فقط — لم يُجرَ إصلاح تلقائي. + .audit-fix-any-errors-detected = AUDIT هل تريد إصلاح الأخطاء المكتشفة؟ [نعم / لا] <لا>: + .audit-error-s-warning-s-found = AUDIT: تم العثور على __ocs_fmt_0__ خطأ و__ocs_fmt_1__ تحذير. + .audit-repair-s-applied-issue-s-left = AUDIT: تم تطبيق __ocs_fmt_0__ إصلاح، و__ocs_fmt_1__ مشكلة بلا حل. .audit-scanned-total-object-s = AUDIT: فُحص __ocs_fmt_0__ كائن. .above-text = أعلى النص .active-dim-style-set-to-name-arg = عُيّن نمط الأبعاد النشط إلى "__ocs_fmt_0__" diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index b7df2ac73..f7611ac13 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Възстановяването не успя да генерира използваеми чертожни данни. Прегледай отчета и опитай резервно копие или копие от автоматично запазване. .entities-checked = Проверени обекти .issues-found = Открити проблеми - .entities-removed = Премахнати обекти .references-checked = Проверени препратки - .referenced-entities-removed = Премахнати препратени обекти .references-unavailable = Препратките не са налични .log-path = Дневник за възстановяване .log-write-failed = Дневникът за възстановяване не можа да бъде записан @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = Употреба: UNDO [брой стъпки] .used-for-the-first-save-of-a-new-drawing-exist = Използва се при първото запазване на нов чертеж. Съществуващите чертежи запазват своя тип файл и версия. .visual-style-label = Визуален стил: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Предупреждение: __ocs_fmt_0__ повредени обекта отхвърлени (грешка в анализатора — лоши нормали / брой) - .warning-corrupt-xref-entities-dropped = Предупреждение: __ocs_fmt_0__ повредени xref обекта отхвърлени .xref-loaded = XREF Зареден "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: не може да се създаде ZIP за предаване (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: папката не може да бъде създадена (__ocs_fmt_1__). @@ -5638,9 +5634,9 @@ styles = .aci-color-index = ACI Цветови индекс .aci = ACI: .audit-no-issues-found = AUDIT: не са открити проблеми. - .audit-reference-s-to-undefined-block-s = AUDIT: препратка/и към недефинирани блок(ове): __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: препратка/и към недефинирани слой(еве): __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: само отчет — не е извършена автоматична поправка. + .audit-fix-any-errors-detected = AUDIT Да се поправят ли откритите грешки? [Да / Не] <Не>: + .audit-error-s-warning-s-found = AUDIT: открити грешки: __ocs_fmt_0__, предупреждения: __ocs_fmt_1__. + .audit-repair-s-applied-issue-s-left = AUDIT: приложени поправки: __ocs_fmt_0__, нерешени проблеми: __ocs_fmt_1__. .audit-scanned-total-object-s = AUDIT: сканирани __ocs_fmt_0__ обект(а). .above-text = Над текста .active-dim-style-set-to-name-arg = Активният стил за оразмеряване е зададен на "__ocs_fmt_0__" diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index 1aeb662fd..9daf336ac 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Při obnovení se nepodařilo získat použitelná data výkresu. Projděte zprávu a zkuste zálohu nebo automaticky uloženou kopii. .entities-checked = Zkontrolované entity .issues-found = Nalezené problémy - .entities-removed = Odstraněné entity .references-checked = Zkontrolované reference - .referenced-entities-removed = Odstraněné odkazované entity .references-unavailable = Nedostupné reference .log-path = Protokol obnovení .log-write-failed = Protokol obnovení se nepodařilo zapsat @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = Použití: UNDO [počet kroků] .used-for-the-first-save-of-a-new-drawing-exist = Používá se pro první uložení nového výkresu. Stávající výkresy si ponechají svůj typ souboru a verzi. .visual-style-label = Vizuální styl: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Varování: __ocs_fmt_0__ poškozené entity byly odstraněny (nevyžádaná analyzátor – špatné normály / počty) - .warning-corrupt-xref-entities-dropped = Varování: __ocs_fmt_0__ poškozené entity externí reference byly zrušeny .xref-loaded = XREF Načteno "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: nelze vytvořit přenosový ZIP (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: Nelze vytvořit složku (__ocs_fmt_1__). @@ -5635,9 +5631,9 @@ styles = .aci-color-index = Barevný index ACI .aci = ACI: .audit-no-issues-found = AUDIT: nebyly nalezeny žádné problémy. - .audit-reference-s-to-undefined-block-s = AUDIT: reference na nedefinované bloky: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: reference na nedefinované vrstvy: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: pouze zpráva – neprovádí se žádná automatická oprava. + .audit-fix-any-errors-detected = AUDIT Opravit zjištěné chyby? [Ano / Ne] : + .audit-error-s-warning-s-found = AUDIT: nalezeno chyb: __ocs_fmt_0__, varování: __ocs_fmt_1__. + .audit-repair-s-applied-issue-s-left = AUDIT: provedeno oprav: __ocs_fmt_0__, nevyřešeno problémů: __ocs_fmt_1__. .audit-scanned-total-object-s = AUDIT: skenovaný objekt(y) __ocs_fmt_0__. .above-text = Nad textem .active-dim-style-set-to-name-arg = Styl aktivního ztlumení nastaven na "__ocs_fmt_0__" diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index a05910b62..622916ec7 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Die Wiederherstellung konnte keine verwendbaren Zeichnungsdaten erzeugen. Prüfen Sie den Bericht und versuchen Sie eine Sicherungskopie oder automatisch gespeicherte Kopie. .entities-checked = Geprüfte Objekte .issues-found = Gefundene Probleme - .entities-removed = Entfernte Objekte .references-checked = Geprüfte Referenzen - .referenced-entities-removed = Entfernte referenzierte Objekte .references-unavailable = Nicht verfügbare Referenzen .log-path = Wiederherstellungsprotokoll .log-write-failed = Wiederherstellungsprotokoll konnte nicht geschrieben werden @@ -2591,8 +2589,6 @@ file = .usage-undo-number-of-steps = Anwendung: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = Wird für die erste Speicherung einer neuen Zeichnung verwendet. Bestehende Zeichnungen behalten ihren Dateityp und ihre Version bei. .visual-style-label = Visueller Stil: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Warnung: __ocs_fmt_0__ beschädigte Objekte verworfen (ungültige Analysedaten — fehlerhafte Normalen oder Anzahlen) - .warning-corrupt-xref-entities-dropped = Warnung: __ocs_fmt_0__ beschädigte XRef-Objekte verworfen .xref-loaded = XREF Geladen "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: das Übertragungs-ZIP kann nicht erstellt werden (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: kann keinen Ordner erstellen (__ocs_fmt_1__). @@ -5636,9 +5632,9 @@ styles = .aci-color-index = ACI Farbindex .aci = ACI: .audit-no-issues-found = AUDIT: keine Probleme gefunden. - .audit-reference-s-to-undefined-block-s = AUDIT: Verweis(e) auf undefinierte(n) Block(e): __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: Referenz(en) auf undefinierte Ebene(n): __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: Nur Bericht erstatten — keine automatische Reparatur durchgeführt. + .audit-fix-any-errors-detected = AUDIT Gefundene Fehler beheben? [Ja / Nein] : + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ Fehler, __ocs_fmt_1__ Warnung(en) gefunden. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ Reparatur(en) ausgeführt, __ocs_fmt_1__ Problem(e) ungelöst. .audit-scanned-total-object-s = AUDIT: gescanntes __ocs_fmt_0__ Objekt(e). .above-text = Vorstehender Text .active-dim-style-set-to-name-arg = Aktiver Bemaßungsstil auf „__ocs_fmt_0__“ gesetzt diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 207c2e265..a6ff1263e 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -224,9 +224,7 @@ recovery = .failed-description = Η ανάκτηση δεν μπόρεσε να παραγάγει αξιοποιήσιμα δεδομένα σχεδίου. Ελέγξτε την αναφορά και δοκιμάστε ένα αντίγραφο ασφαλείας ή αυτόματης αποθήκευσης. .entities-checked = Οντότητες που ελέγχθηκαν .issues-found = Προβλήματα που βρέθηκαν - .entities-removed = Οντότητες που αφαιρέθηκαν .references-checked = Αναφορές που ελέγχθηκαν - .referenced-entities-removed = Αναφερόμενες οντότητες που αφαιρέθηκαν .references-unavailable = Οι αναφορές δεν είναι διαθέσιμες .log-path = Αρχείο καταγραφής ανάκτησης .log-write-failed = Δεν ήταν δυνατή η εγγραφή του αρχείου καταγραφής ανάκτησης @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = Χρήση: UNDO [αριθμός βημάτων] .used-for-the-first-save-of-a-new-drawing-exist = Χρησιμοποιείται στην πρώτη αποθήκευση ενός νέου σχεδίου. Τα υπάρχοντα σχέδια διατηρούν τον τύπο και την έκδοση του αρχείου τους. .visual-style-label = Οπτικό στυλ: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Προειδοποίηση: απορρίφθηκαν __ocs_fmt_0__ κατεστραμμένες οντότητες (άχρηστα δεδομένα αναλυτή — εσφαλμένα κάθετα διανύσματα / πλήθη) - .warning-corrupt-xref-entities-dropped = Προειδοποίηση: απορρίφθηκαν __ocs_fmt_0__ κατεστραμμένες οντότητες xref .xref-loaded = XREF Φορτώθηκε το "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: δεν είναι δυνατή η δημιουργία του ZIP μεταφοράς (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: δεν είναι δυνατή η δημιουργία φακέλου (__ocs_fmt_1__). @@ -5638,9 +5634,9 @@ styles = .aci-color-index = Δείκτης χρώματος ACI .aci = ACI: .audit-no-issues-found = AUDIT: δεν βρέθηκαν προβλήματα. - .audit-reference-s-to-undefined-block-s = AUDIT: αναφορά(ές) σε μη ορισμένα μπλοκ: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: αναφορά(ές) σε μη ορισμένα επίπεδα: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: μόνο αναφορά — δεν έγινε αυτόματη επιδιόρθωση. + .audit-fix-any-errors-detected = AUDIT Διόρθωση των σφαλμάτων που εντοπίστηκαν; [Ναι / Όχι] <Όχι>: + .audit-error-s-warning-s-found = AUDIT: βρέθηκαν __ocs_fmt_0__ σφάλματα, __ocs_fmt_1__ προειδοποιήσεις. + .audit-repair-s-applied-issue-s-left = AUDIT: εφαρμόστηκαν __ocs_fmt_0__ επιδιορθώσεις, __ocs_fmt_1__ προβλήματα παραμένουν άλυτα. .audit-scanned-total-object-s = AUDIT: σαρώθηκαν __ocs_fmt_0__ αντικείμενο(α). .above-text = Πάνω από το κείμενο .active-dim-style-set-to-name-arg = Το ενεργό στυλ διαστάσεων ορίστηκε σε "__ocs_fmt_0__" diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 7245cf065..4f76f9bb4 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -224,9 +224,7 @@ recovery = .failed-description = Recovery could not produce usable drawing data. Review the report and try a backup or automatic-save copy. .entities-checked = Entities checked .issues-found = Issues found - .entities-removed = Entities removed .references-checked = References checked - .referenced-entities-removed = Referenced entities removed .references-unavailable = References unavailable .log-path = Recovery log .log-write-failed = Recovery log could not be written @@ -2591,8 +2589,6 @@ file = .usage-undo-number-of-steps = Usage: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = Used for the first save of a new drawing. Existing drawings keep their file type and version. .visual-style-label = Visual style: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Warning: __ocs_fmt_0__ corrupt entities dropped (parser junk — bad normals / counts) - .warning-corrupt-xref-entities-dropped = Warning: __ocs_fmt_0__ corrupt xref entities dropped .xref-loaded = XREF Loaded "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: cannot build the transmittal ZIP (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: cannot create folder (__ocs_fmt_1__). @@ -5637,9 +5633,9 @@ styles = .aci-color-index = ACI Color Index .aci = ACI: .audit-no-issues-found = AUDIT: no issues found. - .audit-reference-s-to-undefined-block-s = AUDIT: reference(s) to undefined block(s): __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: reference(s) to undefined layer(s): __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: report only — no automatic repair performed. + .audit-fix-any-errors-detected = AUDIT Fix any errors detected? [Yes / No] : + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ error(s), __ocs_fmt_1__ warning(s) found. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ repair(s) applied, __ocs_fmt_1__ issue(s) left unresolved. .audit-scanned-total-object-s = AUDIT: scanned __ocs_fmt_0__ object(s). .above-text = Above text .active-dim-style-set-to-name-arg = Active dim style set to "__ocs_fmt_0__" diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 99454f537..3a661593e 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = La recuperación no pudo producir datos de dibujo utilizables. Revise el informe e intente usar una copia de seguridad o de guardado automático. .entities-checked = Entidades comprobadas .issues-found = Problemas encontrados - .entities-removed = Entidades eliminadas .references-checked = Referencias comprobadas - .referenced-entities-removed = Entidades referenciadas eliminadas .references-unavailable = Referencias no disponibles .log-path = Registro de recuperación .log-write-failed = No se pudo escribir el registro de recuperación @@ -2591,8 +2589,6 @@ file = .usage-undo-number-of-steps = Uso: UNDO [número de pasos] .used-for-the-first-save-of-a-new-drawing-exist = Se usa para el primer guardado de un dibujo nuevo. Los dibujos existentes conservan su tipo y versión de archivo. .visual-style-label = Estilo visual: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Advertencia: se descartaron __ocs_fmt_0__ entidades dañadas (datos inválidos del analizador: normales o recuentos erróneos) - .warning-corrupt-xref-entities-dropped = Advertencia: se descartaron __ocs_fmt_0__ entidades de referencia externa dañadas .xref-loaded = XREF Se cargó «__ocs_fmt_0__» .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: no se puede crear el ZIP de transmisión (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: no se puede crear la carpeta (__ocs_fmt_1__). @@ -5638,9 +5634,9 @@ styles = .aci-color-index = Índice de color ACI .aci = ACI: .audit-no-issues-found = AUDIT: no se encontraron problemas. - .audit-reference-s-to-undefined-block-s = AUDIT: referencias a bloques no definidos: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: referencias a capas no definidas: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: solo informe; no se realizó ninguna reparación automática. + .audit-fix-any-errors-detected = AUDIT ¿Corregir los errores detectados? [Sí / No] : + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ error(es), __ocs_fmt_1__ advertencia(s) encontrados. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ reparación(es) aplicada(s), __ocs_fmt_1__ problema(s) sin resolver. .audit-scanned-total-object-s = AUDIT: se examinaron __ocs_fmt_0__ objetos. .above-text = Encima del texto .active-dim-style-set-to-name-arg = Estilo de cota activo definido como «__ocs_fmt_0__» diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index e1bb9c20b..b6949eea4 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Palautus ei tuottanut käyttökelpoisia piirustustietoja. Tarkista raportti ja kokeile varmuuskopiota tai automaattisesti tallennettua kopiota. .entities-checked = Tarkistetut entiteetit .issues-found = Havaitut ongelmat - .entities-removed = Poistetut entiteetit .references-checked = Tarkistetut viitteet - .referenced-entities-removed = Poistetut viitatut entiteetit .references-unavailable = Viitteet eivät ole käytettävissä .log-path = Palautusloki .log-write-failed = Palautuslokia ei voitu kirjoittaa @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = Käyttö: UNDO [vaiheiden määrä] .used-for-the-first-save-of-a-new-drawing-exist = Käytetään uuden piirustuksen ensimmäiseen tallennukseen. Olemassa olevat piirustukset säilyttävät tiedostotyyppinsä ja -versionsa. .visual-style-label = Visuaalinen tyyli: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Varoitus: __ocs_fmt_0__-korruptoituneet entiteetit pudotettiin (jäsennysroska - huonot normaalit / määrät) - .warning-corrupt-xref-entities-dropped = Varoitus: __ocs_fmt_0__-korruptoituneet xref-entiteetit putosivat .xref-loaded = XREF Ladattu "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: siirto-ZIP:n luominen epäonnistui (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: kansiota (__ocs_fmt_1__) ei voi luoda. @@ -5637,9 +5633,9 @@ styles = .aci-color-index = ACI väriindeksi .aci = ACI: .audit-no-issues-found = AUDIT: ongelmia ei löytynyt. - .audit-reference-s-to-undefined-block-s = AUDIT: viittaus määrittelemättömiin lohkoihin: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: viittaukset määrittelemättömiin tasoihin: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: vain raportti – automaattista korjausta ei suoritettu. + .audit-fix-any-errors-detected = AUDIT Korjataanko havaitut virheet? [Kyllä / Ei] : + .audit-error-s-warning-s-found = AUDIT: löytyi __ocs_fmt_0__ virhettä, __ocs_fmt_1__ varoitusta. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ korjausta tehty, __ocs_fmt_1__ ongelmaa ratkaisematta. .audit-scanned-total-object-s = AUDIT: skannatut __ocs_fmt_0__-objektit. .above-text = Tekstin yläpuolella .active-dim-style-set-to-name-arg = Aktiivinen himmennystyyli asetettu "__ocs_fmt_0__" diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index f579c49a0..0fef10b0d 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = La récupération n'a pas produit de données de dessin utilisables. Consultez le rapport et essayez une sauvegarde ou une copie d'enregistrement automatique. .entities-checked = Entités vérifiées .issues-found = Problèmes détectés - .entities-removed = Entités supprimées .references-checked = Références vérifiées - .referenced-entities-removed = Entités référencées supprimées .references-unavailable = Références indisponibles .log-path = Journal de récupération .log-write-failed = Impossible d'écrire le journal de récupération @@ -2591,8 +2589,6 @@ file = .usage-undo-number-of-steps = Utilisation : UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = Utilisé pour la première sauvegarde d'un nouveau dessin. Les dessins existants conservent leur type de fichier et leur version. .visual-style-label = Style visuel : __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Avertissement : __ocs_fmt_0__ objet(s) corrompu(s) ignoré(s) (données d’analyse invalides — normales ou nombres incorrects) - .warning-corrupt-xref-entities-dropped = Avertissement : __ocs_fmt_0__ objet(s) de référence externe corrompu(s) ignoré(s) .xref-loaded = XREF Charge "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__ : impossible de créer le ZIP de transmission (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: ne peut pas créer de dossier (__ocs_fmt_1__). @@ -5639,9 +5635,9 @@ styles = .aci-color-index = ACI Indice de couleur .aci = ACI: .audit-no-issues-found = AUDIT: aucun problème trouvé. - .audit-reference-s-to-undefined-block-s = AUDIT: référence(s) à un ou plusieurs blocs non définis: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT : références à des calques non définis : __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: rapport seulement — aucune réparation automatique n'est effectuée. + .audit-fix-any-errors-detected = AUDIT Corriger les erreurs détectées ? [Oui / Non] : + .audit-error-s-warning-s-found = AUDIT : __ocs_fmt_0__ erreur(s), __ocs_fmt_1__ avertissement(s) trouvé(s). + .audit-repair-s-applied-issue-s-left = AUDIT : __ocs_fmt_0__ réparation(s) appliquée(s), __ocs_fmt_1__ problème(s) non résolu(s). .audit-scanned-total-object-s = AUDIT : objets analysés : __ocs_fmt_0__. .above-text = Texte ci-dessus .active-dim-style-set-to-name-arg = Style de cote courant défini sur « __ocs_fmt_0__ » diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 62bc1707e..386c0b299 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = पुनर्प्राप्ति उपयोग योग्य ड्रॉइंग डेटा नहीं बना सकी। रिपोर्ट की समीक्षा करें और बैकअप या स्वतः-सहेजी गई प्रति आज़माएँ। .entities-checked = जाँची गई एंटिटियाँ .issues-found = मिली समस्याएँ - .entities-removed = हटाई गई एंटिटियाँ .references-checked = जाँचे गए संदर्भ - .referenced-entities-removed = हटाई गई संदर्भित एंटिटियाँ .references-unavailable = अनुपलब्ध संदर्भ .log-path = पुनर्प्राप्ति लॉग .log-write-failed = पुनर्प्राप्ति लॉग लिखा नहीं जा सका @@ -2579,8 +2577,6 @@ file = .usage-undo-number-of-steps = उपयोग: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = नई ड्रॉइंग को पहली बार सहेजते समय उपयोग होता है। मौजूदा ड्रॉइंग अपना फ़ाइल प्रकार और संस्करण बनाए रखती हैं। .visual-style-label = दृश्य शैली: __ocs_fmt_0__ - .warning-corrupt-entities-dropped-parser-junk-b = चेतावनी: __ocs_fmt_0__ दूषित ऑब्जेक्ट छोड़े गए (अमान्य पार्सर डेटा — गलत नॉर्मल या गिनती) - .warning-corrupt-xref-entities-dropped = चेतावनी: __ocs_fmt_0__ दूषित xref ऑब्जेक्ट छोड़े गए .xref-loaded = XREF लोड हो गया "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: ट्रांसमिट ZIP नहीं बनाया जा सकता (__ocs_fmt_1__)। .cmd-cannot-create-folder-e = __ocs_fmt_0__: फ़ोल्डर नहीं बना सकता (__ocs_fmt_1__). @@ -5626,9 +5622,9 @@ styles = .aci-color-index = ACI रंग सूचकांक .aci = ACI: .audit-no-issues-found = AUDIT: कोई समस्या नहीं मिली। - .audit-reference-s-to-undefined-block-s = AUDIT: संदर्भ (s) अपरिभाषित ब्लॉकों के लिए: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: अपरिभाषित लेयर के संदर्भ: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: केवल रिपोर्ट - कोई स्वचालित मरम्मत नहीं की जाती है। + .audit-fix-any-errors-detected = AUDIT पाई गई त्रुटियाँ ठीक करें? [हाँ / नहीं] <नहीं>: + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ त्रुटि(याँ), __ocs_fmt_1__ चेतावनी(याँ) मिलीं। + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ सुधार लागू हुए, __ocs_fmt_1__ समस्या(एँ) अनसुलझी रहीं। .audit-scanned-total-object-s = AUDIT: __ocs_fmt_0__ ऑब्जेक्ट जाँचे गए। .above-text = पाठ के ऊपर .active-dim-style-set-to-name-arg = सक्रिय मंद शैली "__ocs_fmt_0__" के लिए सेट diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 5aa461c1c..66cf9695f 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -224,9 +224,7 @@ recovery = .failed-description = A helyreállítás nem eredményezett használható rajzadatokat. Tekintse át a jelentést, és próbáljon meg egy biztonsági vagy automatikusan mentett példányt. .entities-checked = Ellenőrzött entitások .issues-found = Talált problémák - .entities-removed = Eltávolított entitások .references-checked = Ellenőrzött hivatkozások - .referenced-entities-removed = Eltávolított hivatkozott entitások .references-unavailable = Nem elérhető hivatkozások .log-path = Helyreállítási napló .log-write-failed = A helyreállítási napló nem írható @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = Használat: UNDO [lépések száma] .used-for-the-first-save-of-a-new-drawing-exist = Egy új rajz első mentésénél használatos. A meglévő rajzok megtartják fájltípusukat és verziójukat. .visual-style-label = Vizuális stílus: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Figyelmeztetés: __ocs_fmt_0__ sérült objektum kihagyva (érvénytelen adatok: hibás normálvektorok / elemszámok) - .warning-corrupt-xref-entities-dropped = Figyelmeztetés: __ocs_fmt_0__ sérült xref-objektum kihagyva .xref-loaded = XREF betöltve: "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: nem hozható létre az átviteli ZIP (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: nem hozható létre mappa (__ocs_fmt_1__). @@ -5627,9 +5623,9 @@ styles = .aci-color-index = ACI színindex .aci = ACI: .audit-no-issues-found = AUDIT: nem található probléma. - .audit-reference-s-to-undefined-block-s = AUDIT: hivatkozás(ok) meghatározatlan blokk(ok)ra: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: hivatkozások nem definiált fóliákra: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: csak jelentés – nem történt automatikus javítás. + .audit-fix-any-errors-detected = AUDIT Javítsa az észlelt hibákat? [Igen / Nem] : + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ hiba, __ocs_fmt_1__ figyelmeztetés található. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ javítás alkalmazva, __ocs_fmt_1__ probléma megoldatlan. .audit-scanned-total-object-s = AUDIT: __ocs_fmt_0__ objektum ellenőrizve. .above-text = A szöveg felett .active-dim-style-set-to-name-arg = Aktív méretezési stílus: „__ocs_fmt_0__” diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 0e0954c76..c9ada8a1e 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Il recupero non ha prodotto dati di disegno utilizzabili. Esamina il rapporto e prova una copia di backup o di salvataggio automatico. .entities-checked = Entità controllate .issues-found = Problemi rilevati - .entities-removed = Entità rimosse .references-checked = Riferimenti controllati - .referenced-entities-removed = Entità referenziate rimosse .references-unavailable = Riferimenti non disponibili .log-path = Registro di recupero .log-write-failed = Impossibile scrivere il registro di recupero @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = Utilizzo: UNDO [numero di passi] .used-for-the-first-save-of-a-new-drawing-exist = Utilizzato per il primo salvataggio di un nuovo disegno. I disegni esistenti mantengono il tipo e la versione del file. .visual-style-label = Stile visivo: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Avviso: entità corrotte __ocs_fmt_0__ eliminate (spazzatura del parser: valori normali/conteggi errati) - .warning-corrupt-xref-entities-dropped = Avviso: entità xrif corrotte __ocs_fmt_0__ eliminate .xref-loaded = XREF Caricato "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: impossibile creare il ZIP di trasmissione (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: impossibile creare la cartella (__ocs_fmt_1__). @@ -5637,9 +5633,9 @@ styles = .aci-color-index = ACI Indice colori .aci = ACI: .audit-no-issues-found = AUDIT: nessun problema trovato. - .audit-reference-s-to-undefined-block-s = AUDIT: riferimento/i a blocchi non definiti: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: riferimento/i a livelli non definiti: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: solo rapporto: nessuna riparazione automatica eseguita. + .audit-fix-any-errors-detected = AUDIT Correggere gli errori rilevati? [Sì / No] : + .audit-error-s-warning-s-found = AUDIT: trovati __ocs_fmt_0__ errore/i, __ocs_fmt_1__ avviso/i. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ riparazione/i applicata/e, __ocs_fmt_1__ problema/i irrisolto/i. .audit-scanned-total-object-s = AUDIT: oggetto/i __ocs_fmt_0__ scansionato/i. .above-text = Sopra il testo .active-dim-style-set-to-name-arg = Stile di attenuazione attivo impostato su "__ocs_fmt_0__" diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index dbb1852c1..a46d92232 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = 修復処理で使用可能な図面データを生成できませんでした。レポートを確認し、バックアップまたは自動保存コピーをお試しください。 .entities-checked = 確認したエンティティ .issues-found = 検出した問題 - .entities-removed = 削除したエンティティ .references-checked = 確認した参照 - .referenced-entities-removed = 削除した参照エンティティ .references-unavailable = 使用できない参照 .log-path = 修復ログ .log-write-failed = 修復ログを書き込めませんでした @@ -2581,8 +2579,6 @@ file = .usage-undo-number-of-steps = 使用法: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = 新しい図面の初回保存時に使用されます。既存の図面ではファイル形式とバージョンが維持されます。 .visual-style-label = 表示スタイル: __ocs_fmt_0__。 - .warning-corrupt-entities-dropped-parser-junk-b = 警告: __ocs_fmt_0__ 個の破損した図形を除外しました(パーサーの不正データ — 法線 / 数の異常) - .warning-corrupt-xref-entities-dropped = 警告: __ocs_fmt_0__ 個の破損した外部参照図形を除外しました .xref-loaded = XREF 「__ocs_fmt_0__」をロードしました .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: 転送 ZIP を作成できません(__ocs_fmt_1__)。 .cmd-cannot-create-folder-e = __ocs_fmt_0__: フォルダーを作成できません(__ocs_fmt_1__)。 @@ -5626,9 +5622,9 @@ styles = .aci-color-index = ACI カラーインデックス .aci = ACI: .audit-no-issues-found = AUDIT: 問題は見つかりませんでした。 - .audit-reference-s-to-undefined-block-s = AUDIT: 未定義ブロックへの参照: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: 未定義レイヤーへの参照: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: レポートのみ — 自動修復は行いませんでした。 + .audit-fix-any-errors-detected = AUDIT 検出されたエラーを修正しますか? [はい / いいえ] <いいえ>: + .audit-error-s-warning-s-found = AUDIT: エラー __ocs_fmt_0__ 件、警告 __ocs_fmt_1__ 件が見つかりました。 + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ 件の修復を適用し、__ocs_fmt_1__ 件の問題が未解決です。 .audit-scanned-total-object-s = AUDIT: __ocs_fmt_0__ 個のオブジェクトを検査しました。 .above-text = 文字の上 .active-dim-style-set-to-name-arg = 現在の寸法スタイルを "__ocs_fmt_0__" に設定しました diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index b2407e787..8acec68a9 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = 복구 과정에서 사용 가능한 도면 데이터를 만들지 못했습니다. 보고서를 검토하고 백업 또는 자동 저장 사본을 사용해 보세요. .entities-checked = 검사한 엔티티 .issues-found = 발견된 문제 - .entities-removed = 제거된 엔티티 .references-checked = 검사한 참조 - .referenced-entities-removed = 제거된 참조 엔티티 .references-unavailable = 사용할 수 없는 참조 .log-path = 복구 로그 .log-write-failed = 복구 로그를 쓸 수 없습니다 @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = 사용법: UNDO [단계 수] .used-for-the-first-save-of-a-new-drawing-exist = 새 도면을 처음 저장할 때 사용됩니다. 기존 도면은 파일 유형과 버전을 유지합니다. .visual-style-label = 시각적 스타일: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = 경고: __ocs_fmt_0__ 손상된 엔터티가 삭제됨(파서 정크 - 잘못된 노멀/카운트) - .warning-corrupt-xref-entities-dropped = 경고: __ocs_fmt_0__ 손상된 외부 참조 엔티티가 삭제되었습니다. .xref-loaded = XREF가 "__ocs_fmt_0__"를 로드했습니다. .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: 전송 ZIP을 만들 수 없습니다(__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: 폴더(__ocs_fmt_1__)를 생성할 수 없습니다. @@ -5637,9 +5633,9 @@ styles = .aci-color-index = ACI 컬러 인덱스 .aci = ACI: .audit-no-issues-found = AUDIT: 문제가 발견되지 않았습니다. - .audit-reference-s-to-undefined-block-s = AUDIT: 정의되지 않은 블록에 대한 참조: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: 정의되지 않은 레이어에 대한 참조: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: 보고 전용 - 자동 복구가 수행되지 않습니다. + .audit-fix-any-errors-detected = AUDIT 감지된 오류를 수정하시겠습니까? [예 / 아니요] <아니요>: + .audit-error-s-warning-s-found = AUDIT: 오류 __ocs_fmt_0__개, 경고 __ocs_fmt_1__개를 찾았습니다. + .audit-repair-s-applied-issue-s-left = AUDIT: 복구 __ocs_fmt_0__개 적용, 미해결 문제 __ocs_fmt_1__개. .audit-scanned-total-object-s = AUDIT: __ocs_fmt_0__ 개체를 스캔했습니다. .above-text = 텍스트 위 .active-dim-style-set-to-name-arg = 활성 밝기 스타일이 "__ocs_fmt_0__"로 설정됨 diff --git a/locales/lo-LA/opencadstudio.ftl b/locales/lo-LA/opencadstudio.ftl index 044bcf559..4d8dfbd42 100644 --- a/locales/lo-LA/opencadstudio.ftl +++ b/locales/lo-LA/opencadstudio.ftl @@ -224,9 +224,7 @@ recovery = .failed-description = ການກູ້ຄືນບໍ່ສາມາດສ້າງຂໍ້ມູນຮູບແຕ້ມທີ່ໃຊ້ງານໄດ້. ກະລຸນາກວດສອບລາຍງານ ແລະ ລອງໃຊ້ສຳເນົາສຳຮອງ ຫຼື ໄຟລ໌ບັນທຶກອັດຕະໂນມັດ. .entities-checked = ອົງປະກອບທີ່ກວດສອບແລ້ວ .issues-found = ບັນຫາທີ່ພົບ - .entities-removed = ອົງປະກອບທີ່ຖືກລຶບອອກ .references-checked = ຈຸດອ້າງອີງທີ່ກວດສອບແລ້ວ - .referenced-entities-removed = ອົງປະກອບອ້າງອີງທີ່ຖືກລຶບອອກ .references-unavailable = ຈຸດອ້າງອີງບໍ່ພ້ອມໃຊ້ງານ .log-path = ບັນທຶກເຫດການການກູ້ຄືນ .log-write-failed = ບໍ່ສາມາດຂຽນບັນທຶກເຫດການການກູ້ຄືນໄດ້ @@ -2598,8 +2596,6 @@ file = .usage-undo-number-of-steps = ວິທີໃຊ້: UNDO [ຈຳນວນຂັ້ນຕອນ] .used-for-the-first-save-of-a-new-drawing-exist = ໃຊ້ສຳລັບການບັນທຶກຄັ້ງທຳອິດຂອງແບບແຕ້ມໃໝ່. ແບບແຕ້ມທີ່ມີຢູ່ແລ້ວຈະຮັກສາປະເພດໄຟລ໌ ແລະ ເວີຊັນເດີມໄວ້. .visual-style-label = ຮູບແບບມຸມມອງ: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = ຄຳເຕືອນ: ຕັດອົງປະກອບທີ່ເສຍຫາຍຖິ້ມ __ocs_fmt_0__ ອັນ (ຂໍ້ມູນເສດຈາກການວິເຄາະ — ຄ່າແນວຕັ້ງສາກ/ຈຳນວນຜິດພາດ) - .warning-corrupt-xref-entities-dropped = ຄຳເຕືອນ: ຕັດອົງປະກອບ xref ທີ່ເສຍຫາຍຖິ້ມ __ocs_fmt_0__ ອັນ .xref-loaded = XREF ໂຫຼດແລ້ວ "__ocs_fmt_0__" .cmd-cannot-create-folder-e = __ocs_fmt_0__: ບໍ່ສາມາດສ້າງໂຟລເດີໄດ້ (__ocs_fmt_1__). .cmd-packaged-copied-file-s-into = __ocs_fmt_0__: ລວມໄຟລ໌ ແລະ ສຳເນົາ __ocs_fmt_1__ ໄຟລ໌ ລົງໃນ __ocs_fmt_2__ @@ -5638,9 +5634,9 @@ styles = .aci-color-index = ດັດຊະນີສີ ACI .aci = ACI: .audit-no-issues-found = AUDIT: ບໍ່ພົບຂໍ້ຜິດພາດ. - .audit-reference-s-to-undefined-block-s = AUDIT: ການອ້າງອີງເຖິງບລັອກທີ່ບໍ່ໄດ້ກຳນົດ: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: ການອ້າງອີງເຖິງເລເຢີທີ່ບໍ່ໄດ້ກຳນົດ: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: ລາຍງານເທົ່ານັ້ນ — ບໍ່ໄດ້ມີການສ້ອມແປງອັດຕະໂນມັດ. + .audit-fix-any-errors-detected = AUDIT ແກ້ໄຂຂໍ້ຜິດພາດທີ່ກວດພົບບໍ? [ແມ່ນ / ບໍ່] <ບໍ່>: + .audit-error-s-warning-s-found = AUDIT: ພົບຂໍ້ຜິດພາດ __ocs_fmt_0__ ລາຍການ, ຄຳເຕືອນ __ocs_fmt_1__ ລາຍການ. + .audit-repair-s-applied-issue-s-left = AUDIT: ສ້ອມແປງແລ້ວ __ocs_fmt_0__ ລາຍການ, ບັນຫາທີ່ຍັງບໍ່ໄດ້ແກ້ __ocs_fmt_1__ ລາຍການ. .audit-scanned-total-object-s = AUDIT: ສະແກນທັງໝົດ __ocs_fmt_0__ ວັດຖຸ. .above-text = ເທິງຂໍ້ຄວາມ .active-dim-style-set-to-name-arg = ຮູບແບບຂະໜາດທີ່ໃຊ້ງານຕັ້ງເປັນ "__ocs_fmt_0__" diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index 62d129e43..90bbc64e7 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Het herstel kon geen bruikbare tekeninggegevens opleveren. Controleer het rapport en probeer een reservekopie of automatisch opgeslagen kopie. .entities-checked = Gecontroleerde objecten .issues-found = Gevonden problemen - .entities-removed = Verwijderde objecten .references-checked = Gecontroleerde verwijzingen - .referenced-entities-removed = Verwijderde objecten waarnaar werd verwezen .references-unavailable = Niet-beschikbare verwijzingen .log-path = Herstellogboek .log-write-failed = Het herstellogboek kon niet worden geschreven @@ -2591,8 +2589,6 @@ file = .usage-undo-number-of-steps = Gebruik: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = Gebruikt voor de eerste opslag van een nieuwe tekening. Bestaande tekeningen houden hun bestandstype en versie. .visual-style-label = Visuele stijl: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Waarschuwing: __ocs_fmt_0__ beschadigde objecten overgeslagen (ongeldige parsergegevens — foutieve normalen of aantallen) - .warning-corrupt-xref-entities-dropped = Waarschuwing: __ocs_fmt_0__ beschadigde xref-objecten overgeslagen .xref-loaded = XREF geladen "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: kan de transmissie-ZIP niet maken (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: kan map (__ocs_fmt_1__) niet aanmaken. @@ -5636,9 +5632,9 @@ styles = .aci-color-index = ACI Kleurindex .aci = ACI: .audit-no-issues-found = AUDIT: geen problemen gevonden. - .audit-reference-s-to-undefined-block-s = AUDIT: verwijzing(s) naar ongedefinieerd symbool(en): __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: verwijzing(s) naar ongedefinieerde laag(en): __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: alleen melden + .audit-fix-any-errors-detected = AUDIT Gevonden fouten herstellen? [Ja / Nee] : + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ fout(en), __ocs_fmt_1__ waarschuwing(en) gevonden. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ herstelling(en) toegepast, __ocs_fmt_1__ probleem/problemen onopgelost. .audit-scanned-total-object-s = AUDIT: __ocs_fmt_0__ object(en) gecontroleerd. .above-text = Bovenstaande tekst .active-dim-style-set-to-name-arg = Actieve maatstijl ingesteld op "__ocs_fmt_0__" diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index 6592dcea3..3596e908a 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Odzyskiwanie nie przyniosło użytecznych danych rysunku. Przejrzyj raport i spróbuj użyć kopii zapasowej lub automatycznie zapisanej. .entities-checked = Sprawdzone elementy .issues-found = Znalezione problemy - .entities-removed = Usunięte elementy .references-checked = Sprawdzone odnośniki - .referenced-entities-removed = Usunięte elementy przywoływane .references-unavailable = Niedostępne odnośniki .log-path = Dziennik odzyskiwania .log-write-failed = Nie można zapisać dziennika odzyskiwania @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = Sposób użycia: UNDO [liczba kroków] .used-for-the-first-save-of-a-new-drawing-exist = Używane przy pierwszym zapisie nowego rysunku. Istniejące rysunki zachowują swój typ pliku i wersję. .visual-style-label = Styl wizualny: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Ostrzeżenie: usunięte zostały uszkodzone jednostki __ocs_fmt_0__ (śmieci parsera — złe wartości normalne/liczby) - .warning-corrupt-xref-entities-dropped = Ostrzeżenie: usunięte zostały uszkodzone elementy odnośników zewnętrznych __ocs_fmt_0__ .xref-loaded = XREF Załadowano „__ocs_fmt_0__” .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: nie można utworzyć archiwum ZIP transmittalu (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: nie można utworzyć folderu (__ocs_fmt_1__). @@ -5637,9 +5633,9 @@ styles = .aci-color-index = Indeks kolorów ACI .aci = ACI: .audit-no-issues-found = AUDIT: nie znaleziono żadnych problemów. - .audit-reference-s-to-undefined-block-s = AUDIT: odniesienia do niezdefiniowanych bloków: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: odniesienia do niezdefiniowanych warstw: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: tylko raport — nie wykonano automatycznej naprawy. + .audit-fix-any-errors-detected = AUDIT Naprawić wykryte błędy? [Tak / Nie] : + .audit-error-s-warning-s-found = AUDIT: znaleziono błędy: __ocs_fmt_0__, ostrzeżenia: __ocs_fmt_1__. + .audit-repair-s-applied-issue-s-left = AUDIT: zastosowane naprawy: __ocs_fmt_0__, nierozwiązane problemy: __ocs_fmt_1__. .audit-scanned-total-object-s = AUDIT: zeskanowane obiekty __ocs_fmt_0__. .above-text = Powyżej tekstu .active-dim-style-set-to-name-arg = Aktywny styl przyciemnienia ustawiony na „__ocs_fmt_0__” diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index c4104606b..cf375616e 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = A recuperação não conseguiu produzir dados de desenho utilizáveis. Revise o relatório e tente um backup ou uma cópia de salvamento automático. .entities-checked = Entidades verificadas .issues-found = Problemas encontrados - .entities-removed = Entidades removidas .references-checked = Referências verificadas - .referenced-entities-removed = Entidades referenciadas removidas .references-unavailable = Referências indisponíveis .log-path = Log de recuperação .log-write-failed = Não foi possível gravar o log de recuperação @@ -2591,8 +2589,6 @@ file = .usage-undo-number-of-steps = Uso: UNDO [número de etapas] .used-for-the-first-save-of-a-new-drawing-exist = Usado no primeiro salvamento de um novo desenho. Desenhos existentes mantêm seu tipo e versão de arquivo. .visual-style-label = Estilo visual: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Aviso: __ocs_fmt_0__ entidades corrompidas descartadas (dados inválidos do analisador — normais/contagens incorretas) - .warning-corrupt-xref-entities-dropped = Aviso: __ocs_fmt_0__ entidades de referência externa corrompidas descartadas .xref-loaded = XREF “__ocs_fmt_0__” carregada .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: não foi possível criar o ZIP de transmissão (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: não é possível criar a pasta (__ocs_fmt_1__). @@ -5638,9 +5634,9 @@ styles = .aci-color-index = Índice de cor ACI .aci = ACI: .audit-no-issues-found = AUDIT: nenhum problema encontrado. - .audit-reference-s-to-undefined-block-s = AUDIT: referências a blocos indefinidos: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: referências a camadas indefinidas: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: somente relatório — nenhum reparo automático realizado. + .audit-fix-any-errors-detected = AUDIT Corrigir os erros detectados? [Sim / Não] : + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ erro(s), __ocs_fmt_1__ aviso(s) encontrado(s). + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ reparo(s) aplicado(s), __ocs_fmt_1__ problema(s) não resolvido(s). .audit-scanned-total-object-s = AUDIT: __ocs_fmt_0__ objetos verificados. .above-text = Acima do texto .active-dim-style-set-to-name-arg = Estilo de cota ativo definido como “__ocs_fmt_0__” diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 654ee4628..28467cfbb 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -225,9 +225,7 @@ recovery = .failed-description = Восстановить пригодные данные чертежа не удалось. Просмотрите отчёт и попробуйте резервную или автоматически сохранённую копию. .entities-checked = Проверено объектов .issues-found = Обнаружено проблем - .entities-removed = Удалено объектов .references-checked = Проверено ссылок - .referenced-entities-removed = Удалено ссылочных объектов .references-unavailable = Недоступные ссылки .log-path = Журнал восстановления .log-write-failed = Не удалось записать журнал восстановления @@ -2594,8 +2592,6 @@ file = .usage-undo-number-of-steps = Использование: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = Используется при первом сохранении нового чертежа. Существующие чертежи сохраняют свой тип и версию файла. .visual-style-label = Визуальный стиль: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Предупреждение: повреждённые объекты пропущены: __ocs_fmt_0__ (ошибочные данные анализатора — неверные нормали или количества) - .warning-corrupt-xref-entities-dropped = Предупреждение: повреждённые объекты внешней ссылки пропущены: __ocs_fmt_0__ .xref-loaded = XREF Загруженный "__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: не удалось создать ZIP-пакет передачи (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: не может создавать папку (__ocs_fmt_1__). @@ -5639,9 +5635,9 @@ styles = .aci-color-index = Индекс цвета ACI .aci = ACI: .audit-no-issues-found = AUDIT: не найдено никаких проблем. - .audit-reference-s-to-undefined-block-s = AUDIT: ссылка(ы) на неопределенный(ые) блок(ы): __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: ссылка(ы) на неопределенный(ые) слой(ы): __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: только отчет - не выполняется автоматический ремонт. + .audit-fix-any-errors-detected = AUDIT Исправить обнаруженные ошибки? [Да / Нет] <Нет>: + .audit-error-s-warning-s-found = AUDIT: найдено ошибок: __ocs_fmt_0__, предупреждений: __ocs_fmt_1__. + .audit-repair-s-applied-issue-s-left = AUDIT: применено исправлений: __ocs_fmt_0__, не устранено проблем: __ocs_fmt_1__. .audit-scanned-total-object-s = AUDIT: сканируемый объект (объекты) __ocs_fmt_0__. .above-text = Выше текста .active-dim-style-set-to-name-arg = Активным стилем размеров назначен «__ocs_fmt_0__» diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index c693f75cb..58782aeb8 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -222,9 +222,7 @@ recovery = .failed-description = Kurtarma işlemi kullanılabilir çizim verisi üretemedi. Raporu inceleyip bir yedek veya otomatik kayıt kopyasını deneyin. .entities-checked = Denetlenen obje .issues-found = Bulunan sorun - .entities-removed = Kaldırılan obje .references-checked = Denetlenen referans - .referenced-entities-removed = Referanslardan kaldırılan obje .references-unavailable = Kullanılamayan referans .log-path = Kurtarma günlüğü .log-write-failed = Kurtarma günlüğü yazılamadı @@ -2574,8 +2572,6 @@ file = .usage-undo-number-of-steps = Kullanım: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = Yeni bir çizimin ilk kaydında kullanılır. Mevcut çizimler dosya türünü ve sürümünü korur. .visual-style-label = Görsel stil: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = Uyarı: __ocs_fmt_0__ bozuk nesne atıldı (ayrıştırıcı artığı — hatalı normaller / sayılar) - .warning-corrupt-xref-entities-dropped = Uyarı: __ocs_fmt_0__ bozuk dış referans nesnesi atıldı .xref-loaded = XREF "__ocs_fmt_0__" yüklendi .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: aktarım ZIP'i oluşturulamıyor (__ocs_fmt_1__). .cmd-cannot-create-folder-e = __ocs_fmt_0__: Klasör oluşturulamıyor (__ocs_fmt_1__). @@ -5576,9 +5572,9 @@ styles = .aci-color-index = ACI renk dizini .aci = ACI: .audit-no-issues-found = AUDIT: sorun bulunamadı. - .audit-reference-s-to-undefined-block-s = AUDIT: tanımsız bloklara başvurular: __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: tanımsız katmanlara başvurular: __ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT: yalnızca rapor oluşturuldu; otomatik onarım yapılmadı. + .audit-fix-any-errors-detected = AUDIT Bulunan hatalar düzeltilsin mi? [Evet / Hayır] : + .audit-error-s-warning-s-found = AUDIT: __ocs_fmt_0__ hata, __ocs_fmt_1__ uyarı bulundu. + .audit-repair-s-applied-issue-s-left = AUDIT: __ocs_fmt_0__ onarım uygulandı, __ocs_fmt_1__ sorun çözülemedi. .audit-scanned-total-object-s = AUDIT: __ocs_fmt_0__ nesne tarandı. .above-text = Metnin üstünde .active-dim-style-set-to-name-arg = Etkin ölçü stili "__ocs_fmt_0__" olarak ayarlandı. diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index d6ea27555..7fc56467e 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -224,9 +224,7 @@ recovery = .failed-description = 修复未能生成可用的图形数据。请查看报告并尝试备份或自动保存的副本。 .entities-checked = 已检查实体 .issues-found = 发现的问题 - .entities-removed = 已删除实体 .references-checked = 已检查参照 - .referenced-entities-removed = 已删除被参照实体 .references-unavailable = 不可用参照 .log-path = 修复日志 .log-write-failed = 无法写入修复日志 @@ -2578,8 +2576,6 @@ file = .usage-undo-number-of-steps = 用法: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = 用于新图形的首次保存。现有图形会保留其自身的文件类型和版本。 .visual-style-label = 视觉风格: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = 警告:已丢弃 __ocs_fmt_0__ 个损坏对象(解析数据无效——法线或计数错误) - .warning-corrupt-xref-entities-dropped = 警告:已丢弃 __ocs_fmt_0__ 个损坏的 xref 对象 .xref-loaded = XREF已装入"__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: 无法创建传输 ZIP(__ocs_fmt_1__)。 .cmd-cannot-create-folder-e = __ocs_fmt_0__:无法创建文件夹(__ocs_fmt_1__). @@ -5621,9 +5617,9 @@ styles = .aci-color-index = ACI 颜色索引 .aci = ACI: .audit-no-issues-found = AUDIT:没有找到问题。 - .audit-reference-s-to-undefined-block-s = AUDIT: 未定义块的引用 : __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: 未定义层的参考:__ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT:只报告——没有进行自动修复。 + .audit-fix-any-errors-detected = AUDIT 修复检测到的错误? [是 / 否] <否>: + .audit-error-s-warning-s-found = AUDIT: 发现 __ocs_fmt_0__ 个错误,__ocs_fmt_1__ 个警告。 + .audit-repair-s-applied-issue-s-left = AUDIT: 已应用 __ocs_fmt_0__ 项修复,__ocs_fmt_1__ 个问题未解决。 .audit-scanned-total-object-s = AUDIT: 扫描__ocs_fmt_0__对象。 .above-text = 上方为文本 .active-dim-style-set-to-name-arg = 当前标注样式已设为“__ocs_fmt_0__” diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index d985bea3c..5fc4d9f23 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -224,9 +224,7 @@ recovery = .failed-description = 修復未能產生可用的圖形資料。請查看報告並嘗試備份或自動儲存的副本。 .entities-checked = 已檢查實體 .issues-found = 發現的問題 - .entities-removed = 已刪除實體 .references-checked = 已檢查參照 - .referenced-entities-removed = 已刪除被參照實體 .references-unavailable = 不可用參照 .log-path = 修復日誌 .log-write-failed = 無法寫入修復日誌 @@ -2590,8 +2588,6 @@ file = .usage-undo-number-of-steps = 用法: UNDO [number of steps] .used-for-the-first-save-of-a-new-drawing-exist = 用於新圖形的首次儲存。現有圖形會保留其自身的檔案類型和版本。 .visual-style-label = 視覺風格: __ocs_fmt_0__. - .warning-corrupt-entities-dropped-parser-junk-b = 警告:已丟棄 __ocs_fmt_0__ 個損壞物件(解析資料無效——法線或計數錯誤) - .warning-corrupt-xref-entities-dropped = 警告:已丟棄 __ocs_fmt_0__ 個損壞的 xref 物件 .xref-loaded = XREF已載入"__ocs_fmt_0__" .cmd-cannot-build-the-transmittal-zip-e = __ocs_fmt_0__: 無法建立傳送 ZIP(__ocs_fmt_1__)。 .cmd-cannot-create-folder-e = __ocs_fmt_0__:無法建立資料夾(__ocs_fmt_1__). @@ -5633,9 +5629,9 @@ styles = .aci-color-index = ACI 顏色索引 .aci = ACI: .audit-no-issues-found = AUDIT:沒有找到問題。 - .audit-reference-s-to-undefined-block-s = AUDIT: 未定義圖塊的引用 : __ocs_fmt_0__ - .audit-reference-s-to-undefined-layer-s = AUDIT: 未定義層的參考:__ocs_fmt_0__ - .audit-report-only-no-automatic-repair-performe = AUDIT:只報告——沒有進行自動修復。 + .audit-fix-any-errors-detected = AUDIT 修復偵測到的錯誤? [是 / 否] <否>: + .audit-error-s-warning-s-found = AUDIT: 發現 __ocs_fmt_0__ 個錯誤,__ocs_fmt_1__ 個警告。 + .audit-repair-s-applied-issue-s-left = AUDIT: 已套用 __ocs_fmt_0__ 項修復,__ocs_fmt_1__ 個問題未解決。 .audit-scanned-total-object-s = AUDIT: 掃描__ocs_fmt_0__物件。 .above-text = 上方為文字 .active-dim-style-set-to-name-arg = 目前標註樣式已設為“__ocs_fmt_0__” diff --git a/plugins/opencad-python/Cargo.lock b/plugins/opencad-python/Cargo.lock index b4227ff83..11cfbc9aa 100644 --- a/plugins/opencad-python/Cargo.lock +++ b/plugins/opencad-python/Cargo.lock @@ -1245,6 +1245,15 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "oem_cp" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7959d3349f484aec36462f98226983578bf7d33f9b034c32967489c7000e1f" +dependencies = [ + "phf 0.11.3", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1264,7 +1273,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.6.0" -source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=102f04c#102f04c8ecda1cd409f7ecc4b6eab2dc895c9095" +source = "git+https://github.com/HakanSeven12/opencadcodec.git?rev=325fa98#325fa98d2b881f48e106a830d5cf161624f63131" dependencies = [ "anyhow", "bitflags", @@ -1276,6 +1285,7 @@ dependencies = [ "itoa", "memmap2", "nom", + "oem_cp", "once_cell", "rayon", "ryu", diff --git a/plugins/opencad-python/examples/create_layout_fixture.rs b/plugins/opencad-python/examples/create_layout_fixture.rs index b76e2158b..5cff8d471 100644 --- a/plugins/opencad-python/examples/create_layout_fixture.rs +++ b/plugins/opencad-python/examples/create_layout_fixture.rs @@ -41,7 +41,7 @@ fn main() -> Result<(), Box> { viewport.twist_angle = std::f64::consts::FRAC_PI_2; viewport.view_target = Vector3::new(5.0, 10.0, 0.0); } - document.add_entity_to_layout(EntityType::Viewport(viewport), "Sheet")?; + document.add_entity_to_layout(EntityType::Viewport(Box::new(viewport)), "Sheet")?; let mut file = std::fs::OpenOptions::new() .write(true) diff --git a/plugins/opencad-python/src/ocs_module.rs b/plugins/opencad-python/src/ocs_module.rs index 929268656..04f70baef 100644 --- a/plugins/opencad-python/src/ocs_module.rs +++ b/plugins/opencad-python/src/ocs_module.rs @@ -406,7 +406,7 @@ mod ocs { text.rotation = rotation; host_ctx::with_host(|host| { host_ctx::ensure_undo_started(host); - host.add_entity(EntityType::MText(text)).value() + host.add_entity(EntityType::MText(Box::new(text))).value() }) .ok_or_else(|| vm.new_runtime_error("ocs: not running inside a PY_ command".to_owned())) } diff --git a/src/app/automation.rs b/src/app/automation.rs index 20ed24436..1524e09c9 100644 --- a/src/app/automation.rs +++ b/src/app/automation.rs @@ -762,7 +762,7 @@ impl OpenCADStudio { Err(e) => return err(format!("open: {e}")), }; match crate::io::load_bytes_finalized(&path_buf, bytes) { - Ok((doc, dropped)) => { + Ok(doc) => { let i = self.active_tab; self.tabs[i].scene.clear(); self.tabs[i].scene.document = doc; @@ -784,13 +784,7 @@ impl OpenCADStudio { // The opened document settled (API v9): the post-op // boundary announces `DocumentOpened` once for this load. self.tabs[i].note_document_loaded(); - let mut summary = self.entity_summary(); - if dropped > 0 { - if let Some(obj) = summary.as_object_mut() { - obj.insert("purged".to_string(), json!(dropped)); - } - } - summary + self.entity_summary() } Err(e) => err(format!("open: {e}")), } @@ -1903,8 +1897,7 @@ mod tests { fingerprint: None, }); let bytes = std::fs::read(&path).expect("read the fixture back"); - let (document, _dropped) = - crate::io::load_bytes_finalized(&path, bytes).expect("reparse the fixture"); + let document = crate::io::load_bytes_finalized(&path, bytes).expect("reparse the fixture"); let caches = crate::scene::build_derived_caches_with_progress(&document, &|_| {}, None); let _ = plugin_dispatch_log(); let _ = app.update(crate::app::Message::FileOpened( @@ -2129,7 +2122,7 @@ mod tests { dimension.definition_point = Vector3::new(0.0, 5.0, 0.0); dimension.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); document - .add_entity(EntityType::Dimension(Dimension::Linear(dimension))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))) .unwrap(); crate::modules::draw::modify::explode::bake_dimension_blocks(&mut document); @@ -2152,7 +2145,7 @@ mod tests { dimension.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); app.tabs[app.active_tab] .scene - .add_entity(EntityType::Dimension(Dimension::Linear(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))); let path = std::env::temp_dir().join(format!( "ocs_verified_dimension_{}_{}.dwg", std::process::id(), @@ -2190,7 +2183,7 @@ mod tests { let i = app.active_tab; app.tabs[i] .scene - .add_entity(EntityType::Dimension(Dimension::Linear(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))); let path = std::env::temp_dir().join(format!( "ocs_verified_dimension_follow_up_{}_{}.dwg", std::process::id(), @@ -2240,7 +2233,7 @@ mod tests { app.tabs[i] .scene .document - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); let path = std::env::temp_dir().join(format!( "ocs_verified_dim_{}_{}.dwg", @@ -2330,7 +2323,7 @@ mod tests { viewport.width = 100.0; viewport.height = 50.0; viewport.turn_on(); - scene.add_entity(codec::EntityType::Viewport(viewport)); + scene.add_entity(codec::EntityType::Viewport(Box::new(viewport))); for entity in scene.document.entities_mut() { if let codec::EntityType::Viewport(viewport) = entity { viewport.status.grid_on = true; @@ -2774,7 +2767,7 @@ mod tests { codec::MText::with_value("\\A1;10.5000", codec::types::Vector3::new(10.0, 20.0, 0.0)); app.tabs[i] .scene - .add_entity(codec::EntityType::MText(mtext)); + .add_entity(codec::EntityType::MText(Box::new(mtext))); let q = app.automation_op( r#"{"op":"query","type":"MTEXT","detail":"full","fields":["value","text","height","bounds"]}"#, @@ -3642,7 +3635,7 @@ mod tests { let mut dst_mtext = MText::new(); dst_mtext.value = "DSTM".into(); dst_mtext.height = 2.0; - let dst_mtext_h = app.tabs[i].scene.add_entity(EntityType::MText(dst_mtext)); + let dst_mtext_h = app.tabs[i].scene.add_entity(EntityType::MText(Box::new(dst_mtext))); // Drive the interactive command exactly as the viewport does: // phase 1 source pick, phase 2 destination selection. @@ -3839,7 +3832,7 @@ mod tests { } #[test] - fn open_finalizes_and_purges_like_the_ui_open_path() { + fn open_finalizes_like_the_ui_open_path() { let mut app = OpenCADStudio::new_for_test(); let stale = codec::Handle::from(9999); app.tabs[app.active_tab].scene.solid_models.insert( @@ -3857,26 +3850,13 @@ mod tests { good.center = codec::types::Vector3::new(5.0, 5.0, 0.0); good.radius = 2.0; doc.add_entity(codec::EntityType::Circle(good)).unwrap(); - let mut corrupt = codec::entities::Circle::new(); - corrupt.center = codec::types::Vector3::new(1.0, 1.0, 0.0); - // An absurd radius is rejected; a zero radius is valid. - corrupt.radius = 1.0e11; - doc.add_entity(codec::EntityType::Circle(corrupt)).unwrap(); - let bytes = crate::io::save_to_bytes(&doc, "dxf", doc.version) - .expect("save a document containing a corrupt entity"); + let bytes = crate::io::save_to_bytes(&doc, "dxf", doc.version).expect("save the fixture"); std::fs::write(&path, bytes).unwrap(); let p = path.to_string_lossy().replace('\\', "\\\\"); let result = app.automation_op(&format!(r#"{{"op":"open","path":"{p}"}}"#)); assert_eq!(result["ok"], true, "{}", result["error"]); - assert_eq!( - result["total"], 1, - "the corrupt circle must not survive the open" - ); - assert_eq!( - result["purged"], 1, - "the purge count must be reported, matching the UI open path's diagnostics" - ); + assert_eq!(result["total"], 1); let i = app.active_tab; assert!(!app.tabs[i].scene.solid_models.contains_key(&stale)); diff --git a/src/app/command_driver/clipboard.rs b/src/app/command_driver/clipboard.rs index 64827cad8..8e9d687ab 100644 --- a/src/app/command_driver/clipboard.rs +++ b/src/app/command_driver/clipboard.rs @@ -1405,7 +1405,7 @@ mod paste_entities_kernel_tests { fn remaps_leader_annotation_link_to_pasted_handles() { let mut seed = codec::CadDocument::new(); let note = seed - .add_entity(codec::EntityType::MText(codec::entities::MText::new())) + .add_entity(codec::EntityType::MText(Box::new(codec::entities::MText::new()))) .unwrap(); let mut leader = codec::entities::Leader::default(); leader.annotation_handle = note; diff --git a/src/app/command_driver/dim_edit.rs b/src/app/command_driver/dim_edit.rs index 906b4c636..e845bfe9a 100644 --- a/src/app/command_driver/dim_edit.rs +++ b/src/app/command_driver/dim_edit.rs @@ -36,10 +36,12 @@ impl OpenCADStudio { ) { let i = self.active_tab; let valid = matches!( - self.tabs[i].scene.document.get_entity(dimension), - Some(codec::EntityType::Dimension( - codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - )) + self.tabs[i] + .scene + .document + .get_entity(dimension) + .and_then(crate::entities::dimension::as_dimension), + Some(codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_)) ); if !valid { self.command_line.push_error( @@ -415,8 +417,12 @@ fn apply_dimspace( requested_spacing: Option, ) -> bool { use codec::entities::Dimension; - let (axis, normal, definition, auto_spacing) = match scene.document.get_entity(base_h) { - Some(codec::EntityType::Dimension(dimension @ Dimension::Linear(d))) => { + let base = scene + .document + .get_entity(base_h) + .and_then(crate::entities::dimension::as_dimension); + let (axis, normal, definition, auto_spacing) = match base { + Some(dimension @ Dimension::Linear(d)) => { let spacing = dimension_auto_spacing( &scene.document, dimension, @@ -433,7 +439,7 @@ fn apply_dimspace( spacing, ) } - Some(codec::EntityType::Dimension(dimension @ Dimension::Aligned(d))) => { + Some(dimension @ Dimension::Aligned(d)) => { let spacing = dimension_auto_spacing( &scene.document, dimension, @@ -471,7 +477,7 @@ fn apply_dimspace( kernel::space::move_to_dimension_spacing([p.x, p.y, p.z], frame, target); *p = codec::types::Vector3::new(point[0], point[1], point[2]); }; - match dim { + match &mut **dim { Dimension::Linear(d) => { slide(&mut d.definition_point); d.base.definition_point = d.definition_point; diff --git a/src/app/command_driver/entity_commit.rs b/src/app/command_driver/entity_commit.rs index 559961a35..b4ca6eac0 100644 --- a/src/app/command_driver/entity_commit.rs +++ b/src/app/command_driver/entity_commit.rs @@ -39,10 +39,8 @@ impl OpenCADStudio { let delta_safe = self.delta_add_safe(i, &entity); let pending = self.begin_undo(i, label, 1, delta_safe); let is_associative_dimension = matches!( - entity, - codec::EntityType::Dimension( - codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - ) + crate::entities::dimension::as_dimension(&entity), + Some(codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_)) ); let association_enabled = self.tabs[i].scene.document.header.dimension_associativity == 2; let committed = if preserve_commit_layer { @@ -257,10 +255,8 @@ impl OpenCADStudio { }; let pending = self.begin_undo(i, label, 1, delta_safe); let is_associative_dimension = matches!( - entity, - codec::EntityType::Dimension( - codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - ) + crate::entities::dimension::as_dimension(&entity), + Some(codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_)) ); let association_enabled = self.tabs[i].scene.document.header.dimension_associativity == 2; let committed = if preserve_commit_layer { @@ -324,8 +320,8 @@ impl OpenCADStudio { let label = self.history_label_from_active_cmd(i, "DIMENSION"); let association_mode = self.tabs[i].scene.document.header.dimension_associativity; let single_source_dimension = matches!( - &entity, - codec::EntityType::Dimension(codec::entities::Dimension::Ordinate(_)) + crate::entities::dimension::as_dimension(&entity), + Some(codec::entities::Dimension::Ordinate(_)) ); // A dimension placed on the sheet but measuring model geometry // through a viewport carries the compensation as a negative diff --git a/src/app/command_driver/text_edit.rs b/src/app/command_driver/text_edit.rs index 86cb2b713..3cf316d42 100644 --- a/src/app/command_driver/text_edit.rs +++ b/src/app/command_driver/text_edit.rs @@ -160,7 +160,7 @@ impl OpenCADStudio { Operation::Rotate(degrees) => { dimension.base_mut().text_rotation = degrees.to_radians(); } - Operation::Oblique(degrees) => match dimension { + Operation::Oblique(degrees) => match &mut **dimension { codec::entities::Dimension::Linear(value) => { value.ext_line_rotation = degrees.to_radians(); } diff --git a/src/app/command_driver/transform.rs b/src/app/command_driver/transform.rs index 421cdc274..dc4f070e3 100644 --- a/src/app/command_driver/transform.rs +++ b/src/app/command_driver/transform.rs @@ -463,7 +463,7 @@ impl OpenCADStudio { false } }; - match dim { + match &mut **dim { Dimension::Linear(d) => { stretched |= mv(&mut d.first_point); stretched |= mv(&mut d.second_point); diff --git a/src/app/command_driver/viewport.rs b/src/app/command_driver/viewport.rs index 05c5bfb5c..3208a1ca6 100644 --- a/src/app/command_driver/viewport.rs +++ b/src/app/command_driver/viewport.rs @@ -21,7 +21,7 @@ impl OpenCADStudio { }); let label = self.history_label_from_active_cmd(i, "MVIEW"); let pending = self.begin_undo(i, label, 1, true); - let handle = self.commit_entity_handle(codec::EntityType::Viewport(viewport)); + let handle = self.commit_entity_handle(codec::EntityType::Viewport(Box::new(viewport))); if let (Some(handle), Some(saved)) = (handle, saved_view) { if let Some(codec::EntityType::Viewport(viewport)) = self.tabs[i].scene.document.get_entity_mut(handle) @@ -244,7 +244,8 @@ impl OpenCADStudio { viewport.id = 2; viewport.clip_boundary_handle = clip_handle; viewport.status.non_rectangular_clipping = !clip_handle.is_null(); - let viewport_handle = self.commit_entity_handle(codec::EntityType::Viewport(viewport)); + let viewport_handle = + self.commit_entity_handle(codec::EntityType::Viewport(Box::new(viewport))); if let Some(viewport_handle) = viewport_handle { if !created_boundary { let before = self.tabs[i] diff --git a/src/app/commands/blocks.rs b/src/app/commands/blocks.rs index 5259bc53e..c4ca382f9 100644 --- a/src/app/commands/blocks.rs +++ b/src/app/commands/blocks.rs @@ -1128,7 +1128,7 @@ impl OpenCADStudio { .filter(|br| reload_keys.contains(&br.handle.value())) .map(|br| br.handle) .collect(); - let (infos, _dropped) = crate::io::xref::resolve_xrefs_for_keys( + let infos = crate::io::xref::resolve_xrefs_for_keys( &mut self.tabs[i].scene.document, base_dir, &handles, @@ -1674,7 +1674,7 @@ impl OpenCADStudio { self.tabs[i].xref_unloaded.remove(key); self.tabs[i].xref_stat_cache.remove(key); } - let (infos, _dropped) = crate::io::xref::resolve_xrefs( + let infos = crate::io::xref::resolve_xrefs( &mut self.tabs[i].scene.document, &base_dir, ); diff --git a/src/app/commands/pdf_shx_text.rs b/src/app/commands/pdf_shx_text.rs index 3f500d98e..182448672 100644 --- a/src/app/commands/pdf_shx_text.rs +++ b/src/app/commands/pdf_shx_text.rs @@ -294,7 +294,7 @@ impl OpenCADStudio { } else { line.layer }; - scene.add_entity(codec::EntityType::MText(mtext)); + scene.add_entity(codec::EntityType::MText(Box::new(mtext))); erase.extend(line.handles); } erase.sort(); diff --git a/src/app/commands/sheet_set.rs b/src/app/commands/sheet_set.rs index 3da99868d..c62a06dce 100644 --- a/src/app/commands/sheet_set.rs +++ b/src/app/commands/sheet_set.rs @@ -2389,7 +2389,7 @@ impl OpenCADStudio { Vector3::new(mv.center.x - mv.target.x, mv.center.y - mv.target.y, 0.0); vp.view_height = mv.height; vp.custom_scale = scale; - scene.add_entity(codec::EntityType::Viewport(vp)); + scene.add_entity(codec::EntityType::Viewport(Box::new(vp))); // A paper-space named view of the same name frames it. let mut named = codec::tables::View::new(title.as_str()); named.handle = scene.document.allocate_handle(); diff --git a/src/app/commands/styleprops.rs b/src/app/commands/styleprops.rs index 40de85256..0d7afbbc6 100644 --- a/src/app/commands/styleprops.rs +++ b/src/app/commands/styleprops.rs @@ -3671,53 +3671,62 @@ impl OpenCADStudio { .push_error(crate::tf!("COMPARE: {error}").as_ref()), } } + // AUDIT runs the codec's audit; `AUDIT Yes` also applies its + // repair, undoable as one step. "AUDIT" => { - use std::collections::BTreeSet; - let mut undefined_layers: BTreeSet = BTreeSet::new(); - let mut undefined_blocks: BTreeSet = BTreeSet::new(); - let mut total = 0usize; - { + use crate::command::KeywordCommand; + let c = KeywordCommand::new( + "AUDIT", + "AUDIT Fix any errors detected? [Yes / No] :", + vec![("Yes", "YES", None), ("No", "NO", None)], + ) + .with_default("NO"); + self.command_line.push_info(&c.prompt()); + self.tabs[i].active_cmd = Some(Box::new(c)); + } + cmd if cmd.starts_with("AUDIT ") => { + let fix = cmd[6..].trim().to_uppercase().starts_with('Y'); + let report = self.tabs[i].scene.document.audit(); + let total = { let doc = &self.tabs[i].scene.document; - for e in doc.entities() { - total += 1; - let layer = &e.common().layer; - if !layer.is_empty() && doc.layers.get(layer).is_none() { - undefined_layers.insert(layer.clone()); - } - if let codec::EntityType::Insert(ins) = e { - if doc.block_records.get(&ins.block_name).is_none() { - undefined_blocks.insert(ins.block_name.clone()); - } - } - } - } + doc.entities().count() + doc.objects.len() + }; self.command_line .push_output(crate::tf!("AUDIT: scanned {total} object(s).").as_ref()); - if undefined_layers.is_empty() && undefined_blocks.is_empty() { + if report.is_clean() { self.command_line .push_output(crate::t!("AUDIT: no issues found.").as_ref()); - } else { - if !undefined_layers.is_empty() { - self.command_line.push_error( - crate::tf!( - "AUDIT: reference(s) to undefined layer(s): {}", - undefined_layers.into_iter().collect::>().join(", ") - ) - .as_ref(), - ); - } - if !undefined_blocks.is_empty() { - self.command_line.push_error( - crate::tf!( - "AUDIT: reference(s) to undefined block(s): {}", - undefined_blocks.into_iter().collect::>().join(", ") - ) - .as_ref(), - ); - } - self.command_line.push_info( - crate::t!("AUDIT: report only — no automatic repair performed.").as_ref(), + return Some(Task::none()); + } + self.command_line.push_error( + crate::tf!( + "AUDIT: {} error(s), {} warning(s) found.", + report.error_count(), + report.warning_count() + ) + .as_ref(), + ); + // ponytail: first 50 issues only; the counts above cover the rest. + for issue in report.issues.iter().take(50) { + self.command_line + .push_info(&format!(" {:?}: {}", issue.code, issue.message)); + } + if fix { + self.push_undo_snapshot(i, "AUDIT"); + let repair = self.tabs[i].scene.document.repair(); + self.command_line.push_output( + crate::tf!( + "AUDIT: {} repair(s) applied, {} issue(s) left unresolved.", + repair.actions.len(), + repair.unresolved.len() + ) + .as_ref(), ); + if !repair.actions.is_empty() { + self.tabs[i].dirty = true; + self.tabs[i].scene.rebuild_derived_caches(); + self.refresh_layer_panel(); + } } } diff --git a/src/app/commands/ucsfollow.rs b/src/app/commands/ucsfollow.rs index 77213208c..f76c4075c 100644 --- a/src/app/commands/ucsfollow.rs +++ b/src/app/commands/ucsfollow.rs @@ -126,10 +126,10 @@ mod tests { let i = app.active_tab; let first = app.tabs[i] .scene - .add_entity(codec::EntityType::Viewport(codec::entities::Viewport::new())); + .add_entity(codec::EntityType::Viewport(Box::new(codec::entities::Viewport::new()))); let second = app.tabs[i] .scene - .add_entity(codec::EntityType::Viewport(codec::entities::Viewport::new())); + .add_entity(codec::EntityType::Viewport(Box::new(codec::entities::Viewport::new()))); app.tabs[i].scene.active_viewport = Some(first); let _ = app.run_command_line("UCSFOLLOW 1"); assert!(app.tabs[i].scene.ucs_follow()); diff --git a/src/app/commands/view.rs b/src/app/commands/view.rs index 87e312163..5e7a7dfa7 100644 --- a/src/app/commands/view.rs +++ b/src/app/commands/view.rs @@ -1000,7 +1000,10 @@ impl OpenCADStudio { match self.tabs[i] .scene .document - .add_entity_to_layout(codec::EntityType::Viewport(vp), &layout_name) + .add_entity_to_layout( + codec::EntityType::Viewport(Box::new(vp)), + &layout_name, + ) { Ok(handle) => { self.tabs[i].scene.auto_fit_viewport(handle); @@ -2207,7 +2210,7 @@ mod tests { locked_hatch.common.layer = "LOCKED_LAYER".into(); let h_locked_hatch = app.tabs[i] .scene - .add_entity_clone(EntityType::Hatch(locked_hatch)); + .add_entity_clone(EntityType::Hatch(Box::new(locked_hatch))); let h_line = app.tabs[i] .scene diff --git a/src/app/control/mod.rs b/src/app/control/mod.rs index cd1dccfd1..834b60e26 100644 --- a/src/app/control/mod.rs +++ b/src/app/control/mod.rs @@ -1009,10 +1009,9 @@ impl OpenCADStudio { "new" => { if let Some(template) = req["template"].as_str() { match self.apply_template(template) { - Ok(purged) => { + Ok(()) => { self.set_control_result(json!({ "template": template, - "purged": purged, "total": self.tabs[i].scene.document.entities().count(), })); Task::none() diff --git a/src/app/control/sheets.rs b/src/app/control/sheets.rs index 3045149ac..486929b5a 100644 --- a/src/app/control/sheets.rs +++ b/src/app/control/sheets.rs @@ -434,7 +434,7 @@ impl OpenCADStudio { /// `new` with `"template"` — the web build reads no files from a path, so /// a template is refused there rather than silently ignored. #[cfg(target_arch = "wasm32")] - pub(in crate::app) fn apply_template(&mut self, _template: &str) -> Result { + pub(in crate::app) fn apply_template(&mut self, _template: &str) -> Result<(), Value> { Err(failure( "invalid_request", "starting from a template needs the desktop build", @@ -445,7 +445,7 @@ impl OpenCADStudio { /// file. Tables and styles come from the template; the document keeps no /// source path. #[cfg(not(target_arch = "wasm32"))] - pub(in crate::app) fn apply_template(&mut self, template: &str) -> Result { + pub(in crate::app) fn apply_template(&mut self, template: &str) -> Result<(), Value> { let path = std::path::PathBuf::from(template); let bytes = self .read_drawing(&path) @@ -461,7 +461,7 @@ impl OpenCADStudio { } else { path.clone() }; - let (mut document, purged) = crate::io::load_bytes_finalized(&load_path, bytes) + let mut document = crate::io::load_bytes_finalized(&load_path, bytes) .map_err(|e| failure("template_failed", e))?; document.source_path = Some(path.to_string_lossy().into_owned()); let i = self.active_tab; @@ -482,7 +482,7 @@ impl OpenCADStudio { // A whole document just became resident in the tab (API v9): the // boundary announces `DocumentOpened` once. self.tabs[i].note_document_loaded(); - Ok(purged) + Ok(()) } /// `file_identity` — stable per-document GUID (the drawing's SPMDOCUNIQUE value, diff --git a/src/app/dim_viewport.rs b/src/app/dim_viewport.rs index db3fc9322..49ffaded8 100644 --- a/src/app/dim_viewport.rs +++ b/src/app/dim_viewport.rs @@ -352,7 +352,7 @@ impl OpenCADStudio { fn is_angular_dimension(entity: &EntityType) -> bool { matches!( - entity, - EntityType::Dimension(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) + crate::entities::dimension::as_dimension(entity), + Some(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) ) } diff --git a/src/app/mtext_editor.rs b/src/app/mtext_editor.rs index 2f67342d1..24aa40da0 100644 --- a/src/app/mtext_editor.rs +++ b/src/app/mtext_editor.rs @@ -841,7 +841,7 @@ impl super::OpenCADStudio { // catastrophic cancellation. Insertion is a pure translation, so zeroing // it keeps the layout's shape, wrapping and alignment identical. mt.insertion_point = Vector3::new(0.0, 0.0, 0.0); - let entity = EntityType::MText(mt.clone()); + let entity = EntityType::MText(Box::new(mt.clone())); let anno = 1.0; let bg = self.tabs[i].scene.bg_color; let wires: Vec = tessellate::tessellate( @@ -1753,7 +1753,8 @@ impl super::OpenCADStudio { )); mt.insertion_point = codec::types::Vector3::new(position.x, position.y, position.z); self.push_undo_snapshot(i, "MTEXT"); - let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt))); + let handle = + self.commit_entity_handle(plane.place_entity(EntityType::MText(Box::new(mt)))); if annotative { let scale = self.tabs[i].scene.creation_annotation_scale_handle(); if let (Some(handle), Some(scale)) = (handle, scale) { @@ -1869,7 +1870,8 @@ impl super::OpenCADStudio { )); mt.insertion_point = codec::types::Vector3::new(position.x, position.y, position.z); self.push_undo_snapshot(i, "MTEXT"); - let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt))); + let handle = + self.commit_entity_handle(plane.place_entity(EntityType::MText(Box::new(mt)))); self.tabs[i].dirty = true; if annotative { let scale = self.tabs[i].scene.creation_annotation_scale_handle(); @@ -1885,7 +1887,7 @@ impl super::OpenCADStudio { if let (Some(h), Some(ed)) = (handle, self.mtext_editor.as_mut()) { ed.editing = Some(h); if let Some(EntityType::MText(mtext)) = self.tabs[i].scene.document.get_entity(h) { - ed.original = Some(mtext.clone()); + ed.original = Some((**mtext).clone()); } } } diff --git a/src/app/navigation.rs b/src/app/navigation.rs index 5a7267692..54c8c4e92 100644 --- a/src/app/navigation.rs +++ b/src/app/navigation.rs @@ -497,7 +497,7 @@ mod tests { vp.width = 200.; vp.height = 100.; vp.view_height = 50.; - let handle = scene.add_entity(codec::EntityType::Viewport(vp)); + let handle = scene.add_entity(codec::EntityType::Viewport(Box::new(vp))); scene.active_viewport = Some(handle); let mut camera = scene.navigation_camera(); camera.target = DVec3::new(120., 30., 8.); diff --git a/src/app/plugin_host.rs b/src/app/plugin_host.rs index 3088a9e07..e023cdb31 100644 --- a/src/app/plugin_host.rs +++ b/src/app/plugin_host.rs @@ -943,7 +943,7 @@ impl<'a> HostSession<'a> { frame.common.layer = layer; } self.push_undo("Embed picture"); - let handle = self.add_entity(EntityType::Ole2Frame(frame)); + let handle = self.add_entity(EntityType::Ole2Frame(Box::new(frame))); if handle.is_null() { return Err("the picture frame could not be added".into()); } @@ -6708,7 +6708,7 @@ mod tests { let EntityType::Dimension(dimension) = &mut after else { unreachable!() }; - if let codec::entities::Dimension::Linear(value) = dimension { + if let codec::entities::Dimension::Linear(value) = &mut **dimension { value.second_point.x = 30.0; } ocs_plugin_api::entity_coverage::validate_entity_mutation(&before, &after).unwrap(); @@ -7414,7 +7414,7 @@ mod tests { .unwrap(); let mut viewport = codec::entities::Viewport::new(); viewport.common.owner_handle = owner; - let viewport_handle = host.add_entity(EntityType::Viewport(viewport)); + let viewport_handle = host.add_entity(EntityType::Viewport(Box::new(viewport))); let scale_handle = host.document_mut().allocate_handle(); let mut scale = codec::objects::Scale::new("1:1", 1.0, 1.0); scale.handle = scale_handle; @@ -10861,7 +10861,7 @@ mod tests { bare.height = 30.0; let bare = host .document_mut() - .add_entity(EntityType::Viewport(bare)) + .add_entity(EntityType::Viewport(Box::new(bare))) .unwrap(); assert_eq!( host.document().get_entity(bare).map(|e| match e { diff --git a/src/app/properties.rs b/src/app/properties.rs index e376a84e9..1b88ad023 100644 --- a/src/app/properties.rs +++ b/src/app/properties.rs @@ -1489,12 +1489,14 @@ impl OpenCADStudio { if let Some((anno_field, insert_after)) = anno { let is_anno = crate::scene::annotative::is_annotative(doc, entity) || match entity { - codec::EntityType::Dimension(codec::entities::Dimension::Arc( - dimension, - )) => crate::scene::annotative::dim_style_is_annotative( - doc, - &dimension.base.style_name, - ), + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Arc(_)) => + { + crate::scene::annotative::dim_style_is_annotative( + doc, + &dimension.base().style_name, + ) + } codec::EntityType::Tolerance(_) => { crate::scene::annotative::annotation_style_is_annotative(doc, entity) } @@ -1530,7 +1532,9 @@ impl OpenCADStudio { "annotative", yes_no_choice(t.is_annotative || is_anno), ), - codec::EntityType::Dimension(codec::entities::Dimension::Arc(_)) => { + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Arc(_)) => + { set_row( &mut sections, "annotative", @@ -1683,10 +1687,14 @@ impl OpenCADStudio { format!("{} ({})", t!("Surface"), t!("Extrusion")) } // The reference names an angular dimension by its kind. - codec::EntityType::Dimension(codec::entities::Dimension::Angular2Ln(_)) => { + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Angular2Ln(_)) => + { t!("Angular Dimension").into_owned() } - codec::EntityType::Dimension(codec::entities::Dimension::Angular3Pt(_)) => { + codec::EntityType::Dimension(dimension) + if matches!(**dimension, codec::entities::Dimension::Angular3Pt(_)) => + { t!("3 Point Angular Dimension").into_owned() } codec::EntityType::Underlay(underlay) => match underlay.underlay_type { @@ -1719,22 +1727,14 @@ impl OpenCADStudio { title } else { use codec::entities::Dimension; - match entity { - codec::EntityType::Dimension(Dimension::Aligned(_)) => { - t!("Aligned Dimensional Constraint") - } - codec::EntityType::Dimension(Dimension::Angular2Ln(_)) => { - t!("Angular Dimension (Dynamic)") - } - codec::EntityType::Dimension(Dimension::Angular3Pt(_)) => { + match crate::entities::dimension::as_dimension(entity) { + Some(Dimension::Aligned(_)) => t!("Aligned Dimensional Constraint"), + Some(Dimension::Angular2Ln(_)) => t!("Angular Dimension (Dynamic)"), + Some(Dimension::Angular3Pt(_)) => { t!("3 Point Angular Dimension (Dynamic)") } - codec::EntityType::Dimension(Dimension::Radius(_)) => { - t!("Radius Dimensional Constraint") - } - codec::EntityType::Dimension(Dimension::Diameter(_)) => { - t!("Diameter Dimensional Constraint") - } + Some(Dimension::Radius(_)) => t!("Radius Dimensional Constraint"), + Some(Dimension::Diameter(_)) => t!("Diameter Dimensional Constraint"), _ => t!("Linear Dimensional Constraint"), } .into_owned() @@ -2743,7 +2743,7 @@ handles={handles_ms:.1} panel={:.1} ribbon={ribbon_ms:.1} tail={:.1} selected={} // scale are available. if let codec::EntityType::Dimension(dim) = contextual.as_ref() { if matches!( - dim, + &**dim, codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) ) && !dim.base().text_user_positioned @@ -2780,13 +2780,17 @@ handles={handles_ms:.1} panel={:.1} ribbon={ribbon_ms:.1} tail={:.1} selected={} } } } - let dynamic_angle = match contextual.as_ref() { - codec::EntityType::Dimension( - dim @ (codec::entities::Dimension::Angular2Ln(_) - | codec::entities::Dimension::Angular3Pt(_)), - ) if self.tabs[i].scene.is_dynamic_dimension(handle) => Some(dim), - _ => None, - }; + let contextual_dimension = + crate::entities::dimension::as_dimension(contextual.as_ref()); + let dynamic_angle = contextual_dimension + .filter(|dim| { + matches!( + dim, + codec::entities::Dimension::Angular2Ln(_) + | codec::entities::Dimension::Angular3Pt(_) + ) + }) + .filter(|_| self.tabs[i].scene.is_dynamic_dimension(handle)); if let Some(dim) = dynamic_angle { // A dynamic angle shows a triangle at each end of its arc // pointing away from it, and squares at the arc point and @@ -3060,8 +3064,8 @@ handles={handles_ms:.1} panel={:.1} ribbon={ribbon_ms:.1} tail={:.1} selected={} ) -> Option { let i = self.active_tab; let tracks_dimension_chain = matches!( - &entity, - codec::EntityType::Dimension( + crate::entities::dimension::as_dimension(&entity), + Some( codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) | codec::entities::Dimension::Angular2Ln(_) diff --git a/src/app/update/block_ops_tests.rs b/src/app/update/block_ops_tests.rs index 8afcf5910..5d3c49121 100644 --- a/src/app/update/block_ops_tests.rs +++ b/src/app/update/block_ops_tests.rs @@ -224,7 +224,7 @@ fn fixture_dimension_reference(app: &mut OpenCADStudio) -> String { dimension.base.style_name = "BO_ARROWSTYLE".to_string(); app.tabs[i] .scene - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))); name.to_string() } @@ -244,7 +244,7 @@ fn fixture_dimension_name_reference(app: &mut OpenCADStudio) -> String { dimension.base.style_name = "BO_ARROWNAMESTYLE".to_string(); app.tabs[i] .scene - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))); + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))); name.to_string() } diff --git a/src/app/update/command.rs b/src/app/update/command.rs index 2d2a8ca8e..83e6fbc47 100644 --- a/src/app/update/command.rs +++ b/src/app/update/command.rs @@ -2913,9 +2913,12 @@ impl OpenCADStudio { &value, ); if applied && field == "dim_text_inside" { - if let Some(codec::EntityType::Dimension( - codec::entities::Dimension::LargeRadial(dimension), - )) = app.tabs[i].scene.document.get_entity_mut(handle) + let radial = app.tabs[i] + .scene + .document + .get_entity_mut(handle) + .and_then(crate::entities::dimension::as_dimension_mut); + if let Some(codec::entities::Dimension::LargeRadial(dimension)) = radial { dimension.base.text_user_positioned = false; } @@ -4182,9 +4185,13 @@ impl OpenCADStudio { &val, ); if applied && field == "dim_text_inside" { - if let Some(codec::EntityType::Dimension( - codec::entities::Dimension::LargeRadial(dimension), - )) = self.tabs[i].scene.document.get_entity_mut(handle) + if let Some(codec::entities::Dimension::LargeRadial( + dimension, + )) = self.tabs[i] + .scene + .document + .get_entity_mut(handle) + .and_then(crate::entities::dimension::as_dimension_mut) { dimension.base.text_user_positioned = false; } diff --git a/src/app/update/dialog.rs b/src/app/update/dialog.rs index ea74e5f10..66223bb6a 100644 --- a/src/app/update/dialog.rs +++ b/src/app/update/dialog.rs @@ -886,7 +886,7 @@ impl OpenCADStudio { .filter(|br| dwg_picked.iter().any(|(key, _)| *key == br.handle.value())) .map(|br| br.handle) .collect(); - let (infos, _dropped) = crate::io::xref::resolve_xrefs_for_keys( + let infos = crate::io::xref::resolve_xrefs_for_keys( &mut self.tabs[i].scene.document, &base_dir, &handles, @@ -1093,7 +1093,7 @@ impl OpenCADStudio { self.tabs[i].xref_unloaded.remove(key); self.tabs[i].xref_stat_cache.remove(key); } - let (infos, _dropped) = + let infos = crate::io::xref::resolve_xrefs(&mut self.tabs[i].scene.document, &base_dir); let fresh = crate::io::xref::collect_entries_with_prev( &self.tabs[i].scene.document, diff --git a/src/app/update/file.rs b/src/app/update/file.rs index 3e6338a30..68a52fc92 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -2053,34 +2053,13 @@ impl OpenCADStudio { .xrefs .iter() .any(|item| item.status == crate::io::xref::XrefStatus::Failed); - let document_repaired = parser_errors_recovered - || reference_recovered - || caches.corrupt_dropped > 0 - || caches.xref_dropped > 0; + let document_repaired = parser_errors_recovered || reference_recovered; let recovery_needed = document_repaired || reference_failed; let total_ms = open_started .map(|started| started.elapsed().as_millis() as u32) .unwrap_or(0); self.command_line .push_output(crate::tf!("Opened \"{name}\" — {entity_count} entities").as_ref()); - if caches.corrupt_dropped > 0 { - self.command_line.push_error( - crate::tf!( - "Warning: {} corrupt entities dropped (parser junk — bad normals / counts)", - caches.corrupt_dropped - ) - .as_ref(), - ); - } - if caches.xref_dropped > 0 { - self.command_line.push_error( - crate::tf!( - "Warning: {} corrupt xref entities dropped", - caches.xref_dropped - ) - .as_ref(), - ); - } for info in &caches.xrefs { match info.status { crate::io::xref::XrefStatus::Loaded => { @@ -2180,9 +2159,7 @@ impl OpenCADStudio { size_bytes, caches.source_sha256.clone(), caches.read_stats.clone(), - entity_count.saturating_add(caches.corrupt_dropped), - caches.corrupt_dropped, - caches.xref_dropped, + entity_count, &caches.xrefs, &doc.notifications, document_repaired, diff --git a/src/app/update/graphic_attributes.rs b/src/app/update/graphic_attributes.rs index 3157cd1bc..d34314779 100644 --- a/src/app/update/graphic_attributes.rs +++ b/src/app/update/graphic_attributes.rs @@ -1084,7 +1084,7 @@ mod tests { .document .entities() .filter_map(|entity| match entity { - EntityType::Hatch(hatch) => Some(hatch), + EntityType::Hatch(hatch) => Some(&**hatch), _ => None, }) .collect() diff --git a/src/app/viewport_dimension_tests.rs b/src/app/viewport_dimension_tests.rs index 0866e4f8d..94f0bd326 100644 --- a/src/app/viewport_dimension_tests.rs +++ b/src/app/viewport_dimension_tests.rs @@ -28,7 +28,7 @@ fn fixture() -> (OpenCADStudio, Handle, ViewportFrame) { viewport.custom_scale = 0.1; viewport.view_direction = Vector3::UNIT_Z; viewport.turn_on(); - let viewport = scene.add_entity(EntityType::Viewport(viewport)); + let viewport = scene.add_entity(EntityType::Viewport(Box::new(viewport))); let frame = scene.viewport_frame(viewport).unwrap(); scene.document.header.dimension_associativity = 2; let i = app.active_tab; @@ -323,7 +323,7 @@ fn viewport_dimension_linear_aligned_and_radial_object_picks() { assert_eq!( preview_text( &app, - &EntityType::Dimension(dimension(&app.tabs[i].scene.document).clone()) + &EntityType::Dimension(Box::new(dimension(&app.tabs[i].scene.document).clone())) ), value, "{name}" @@ -361,7 +361,7 @@ fn viewport_dimension_angular_preserves_angle_without_length_factor() { let _ = app.feed_command(StepInput::Point(place)); let doc = &app.tabs[app.active_tab].scene.document; assert_eq!( - preview_text(&app, &EntityType::Dimension(dimension(doc).clone())), + preview_text(&app, &EntityType::Dimension(Box::new(dimension(doc).clone()))), value ); assert!((dimension(doc).measurement() - 90.0).abs() < 1e-5); @@ -1461,9 +1461,9 @@ fn viewport_dimension_invalid_paths_leave_no_partial_association() { Vector3::new(55.0, 60.0, 0.0), ))); for (source, path) in [(model, vec![Handle::new(u64::MAX)]), (leaf, vec![root])] { - let dim = scene.add_entity(EntityType::Dimension(Dimension::Aligned( + let dim = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Aligned( DimensionAligned::new(Vector3::new(50.0, 50.0, 0.0), Vector3::new(55.0, 50.0, 0.0)), - ))); + )))); let invalid = AcceptedSnap { paper_point: DVec3::new(50.0, 50.0, 0.0), model_point: DVec3::ZERO, diff --git a/src/entities/dimension.rs b/src/entities/dimension.rs index 9b3eb9129..7c2bc8d6d 100644 --- a/src/entities/dimension.rs +++ b/src/entities/dimension.rs @@ -3248,7 +3248,7 @@ pub(crate) fn materialize_large_radial_text_position( let Some(EntityType::Dimension(dimension)) = document.get_entity(handle) else { return; }; - if !matches!(dimension, Dimension::LargeRadial(_)) || dimension.base().text_user_positioned { + if !matches!(&**dimension, Dimension::LargeRadial(_)) || dimension.base().text_user_positioned { return; } let source = document.dim_styles.iter().find(|style| { @@ -3262,8 +3262,8 @@ pub(crate) fn materialize_large_radial_text_position( .map(|style| resolved_dimension_style(style, dimension, document)) .map(|style| styled_dimension_text_position(dimension, &style, 1.0)) .unwrap_or_else(|| dimension_text_pos_f64(dimension, None, 2.5, 1.0)); - if let Some(EntityType::Dimension(Dimension::LargeRadial(radial))) = - document.get_entity_mut(handle) + if let Some(Dimension::LargeRadial(radial)) = + document.get_entity_mut(handle).and_then(as_dimension_mut) { radial.base.text_middle_point = position; } @@ -6491,7 +6491,7 @@ fn dimension_text_entity( } mtext.normal = base.normal; mtext.common = base.common.clone(); - return Some(EntityType::MText(mtext)); + return Some(EntityType::MText(Box::new(mtext))); } let value = if style.is_some_and(|style| style.dimtxtdirection) { @@ -7150,7 +7150,7 @@ fn dimension_tolerance_entity( mtext.style = primary_style; mtext.attachment_point = codec::entities::AttachmentPoint::MiddleCenter; mtext.common = primary_common; - return Some(EntityType::MText(mtext)); + return Some(EntityType::MText(Box::new(mtext))); } let mut t = Text::with_value(tol, pos) @@ -9559,3 +9559,22 @@ mod layout_parity_tests { ); } } + +/// The dimension an entity is, if it is one. The variant holds it boxed, so +/// a pattern cannot reach into it; match on this instead. +pub(crate) fn as_dimension(entity: &codec::EntityType) -> Option<&codec::entities::Dimension> { + match entity { + codec::EntityType::Dimension(dimension) => Some(dimension), + _ => None, + } +} + +/// [`as_dimension`], mutably. +pub(crate) fn as_dimension_mut( + entity: &mut codec::EntityType, +) -> Option<&mut codec::entities::Dimension> { + match entity { + codec::EntityType::Dimension(dimension) => Some(dimension), + _ => None, + } +} diff --git a/src/entities/object_data.rs b/src/entities/object_data.rs index d55d2cf86..71f9116bd 100644 --- a/src/entities/object_data.rs +++ b/src/entities/object_data.rs @@ -620,7 +620,7 @@ fn dynamic_data_text(data: &DynamicBlockData) -> String { "{}; dependencies {}; parameters {}; distance multiplier {:.6}; angle {:.6}", value.action.element.name, value.action.dependencies.len(), - value.action.parameter_ids.len(), + value.action.action_ids.len(), value.offsets.distance_multiplier, value.offsets.angle_offset ), @@ -628,14 +628,14 @@ fn dynamic_data_text(data: &DynamicBlockData) -> String { "{}; dependencies {}; parameters {}; connections {}", value.action.element.name, value.action.dependencies.len(), - value.action.parameter_ids.len(), + value.action.action_ids.len(), value.connections.len() ), DynamicBlockData::RotateAction(value) | DynamicBlockData::ScaleAction(value) => format!( "{}; dependencies {}; parameters {}; base {:.6},{:.6},{:.6}; dependent {}", value.action.action.element.name, value.action.action.dependencies.len(), - value.action.action.parameter_ids.len(), + value.action.action.action_ids.len(), value.action.base_point.x, value.action.base_point.y, value.action.base_point.z, diff --git a/src/entities/text_support.rs b/src/entities/text_support.rs index 16e827685..6d8b9d361 100644 --- a/src/entities/text_support.rs +++ b/src/entities/text_support.rs @@ -676,7 +676,9 @@ pub fn adapt_mtext_paragraphs( ATab::Left(_) => TabKind::Left, ATab::Center(_) => TabKind::Center, ATab::Right(_) => TabKind::Right, - ATab::Decimal(..) => TabKind::Decimal, + ATab::Decimal(..) | ATab::DecimalWithCharacter { .. } => { + TabKind::Decimal + } }; TabStop { position: ts.position() as f32 * entity_height, diff --git a/src/entities/traits.rs b/src/entities/traits.rs index 4fc27b30a..9a95575b7 100644 --- a/src/entities/traits.rs +++ b/src/entities/traits.rs @@ -158,6 +158,16 @@ pub trait TextContent { fn replace_text(&mut self, search: &str, rep: &str); } +/// Entity variants holding their entity boxed (MTEXT) dispatch through here. +impl TextContent for Box { + fn text_content(&self) -> Option { + (**self).text_content() + } + fn replace_text(&mut self, search: &str, rep: &str) { + (**self).replace_text(search, rep) + } +} + /// Human-readable variant name used by Quick Select / Select Similar /// filtering. Stable across releases — the strings here are the canonical /// type identifiers throughout the UI. diff --git a/src/entity_creation.rs b/src/entity_creation.rs index f07bfa678..96e5c29c4 100644 --- a/src/entity_creation.rs +++ b/src/entity_creation.rs @@ -638,7 +638,7 @@ pub(crate) fn build_entity( if let Some(style) = text_style_field(spec, document)? { mtext.style = style; } - EntityType::MText(mtext) + EntityType::MText(Box::new(mtext)) } "INSERT" => { let block = spec["block"].as_str().unwrap_or(""); @@ -724,7 +724,7 @@ pub(crate) fn build_entity( let mut path = BoundaryPath::external(); path.add_edge(BoundaryEdge::Polyline(PolylineEdge::new(vertices, true))); hatch.paths.push(path); - EntityType::Hatch(hatch) + EntityType::Hatch(Box::new(hatch)) } other => { return Err(failure( diff --git a/src/io/linetypes.rs b/src/io/linetypes.rs index f029496e5..7afc4b8ba 100644 --- a/src/io/linetypes.rs +++ b/src/io/linetypes.rs @@ -472,6 +472,7 @@ fn complex_elements( scale: decimal(*scale), rotation: decimal(*rot_deg).to_radians(), absolute_rotation: false, + source_flags: 0, offset: [decimal(*x), decimal(*y)], } } @@ -492,6 +493,7 @@ fn complex_elements( scale: decimal(*scale), rotation: decimal(*rot_deg).to_radians(), absolute_rotation: false, + source_flags: 0, offset: [decimal(*x), decimal(*y)], }, }; diff --git a/src/io/mod.rs b/src/io/mod.rs index 11392d93f..fa8a619f7 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -130,7 +130,7 @@ fn recovery_fingerprint_needed(caches: &DerivedCaches) -> bool { crate::io::xref::XrefStatus::Recovered | crate::io::xref::XrefStatus::Failed ) }); - parser_issue || caches.corrupt_dropped > 0 || caches.xref_dropped > 0 || reference_issue + parser_issue || reference_issue } #[derive(Debug, Clone)] @@ -439,17 +439,10 @@ async fn open_path_with_phase_attempt( let parse_ms = t_parse.elapsed().as_millis() as u32; progress2.set(crate::app::OPEN_PHASE_PARSING, 5800, 1000, 1000); let t_purge = Instant::now(); - let dropped = purge_corrupt_entities(&mut doc); - let purge_ms = t_purge.elapsed().as_millis() as u32; - if matches!(attempt, OpenAttempt::Strict) && dropped > 0 { - return Err(OpenAttemptFailure { - message: format!( - "normal read found {dropped} structurally invalid drawing records" - ), - read_stats: Some(read_stats), - recoverable: true, - }); + if matches!(attempt, OpenAttempt::Recovery(..)) { + repair_drawing(&mut doc); } + let purge_ms = t_purge.elapsed().as_millis() as u32; // Before the geometry is prepared below: repairing the // drawing's stripped catalog linetypes after it would leave // the first view drawn without their shapes. None is added: @@ -457,7 +450,7 @@ async fn open_path_with_phase_attempt( crate::io::linetypes::repair_document(&mut doc); progress2.set(crate::app::OPEN_PHASE_XREF, 6000, 0, 1); let t_xref = Instant::now(); - let (xref_infos, xref_dropped) = if let Some(base_dir) = path2.parent() { + let xref_infos = if let Some(base_dir) = path2.parent() { let xref_progress = { let progress = Arc::clone(&progress2); let callback: Arc = @@ -479,7 +472,7 @@ async fn open_path_with_phase_attempt( Some(xref_progress), ) } else { - (Vec::new(), 0) + Vec::new() }; let xref_ms = t_xref.elapsed().as_millis() as u32; progress2.set(crate::app::OPEN_PHASE_CACHING, 7400, 0, 10000); @@ -506,9 +499,7 @@ async fn open_path_with_phase_attempt( // Filled in after `prepare_open_geometry` below. finalize_ms: 0, }; - caches.corrupt_dropped = dropped; caches.read_stats = Some(read_stats); - caches.xref_dropped = xref_dropped; caches.xrefs = xref_infos; if recovery_fingerprint_needed(&caches) { caches.source_sha256 = @@ -800,25 +791,17 @@ async fn load_web_bytes( fix_current_style_names(&mut doc); crate::entities::field::local_header_dates(&mut doc); progress.set(crate::app::OPEN_PHASE_CACHING, 7000, 0, 1); - let dropped = purge_corrupt_entities(&mut doc); - if !recovery_mode && dropped > 0 { - return Err(OpenLoadError { - message: format!("normal read found {dropped} structurally invalid drawing records"), - source_sha256: None, - read_stats: Some(outcome.stats), - recovery_available: true, - }); + if recovery_mode { + repair_drawing(&mut doc); } // XREFs inside the opened drawing resolve from the in-session bytes // registry (see `resolve_web_xrefs`) before the caches snapshot the // document, so merged xref geometry is part of the caches — the same // phase order the native open uses. - let (xref_infos, xref_dropped) = resolve_web_xrefs(&mut doc, progress.clone()).await; + let xref_infos = resolve_web_xrefs(&mut doc, progress.clone()).await; let mut caches = crate::scene::build_derived_caches(&doc); - caches.corrupt_dropped = dropped; caches.read_stats = Some(outcome.stats); caches.xrefs = xref_infos; - caches.xref_dropped = xref_dropped; if source_sha256.is_none() && recovery_fingerprint_needed(&caches) { source_sha256 = web_worker::sha256_document(bytes).await.ok(); } @@ -891,7 +874,7 @@ pub async fn parse_drawing_bytes_web(name: &str, bytes: &[u8]) -> Result, -) -> (Vec, usize) { +) -> Vec { let pending: Vec = doc .block_records .iter() @@ -995,7 +978,7 @@ pub fn load_bytes(name: &str, bytes: Vec) -> Result { } #[cfg(not(target_arch = "wasm32"))] -pub fn load_bytes_finalized(path: &Path, bytes: Vec) -> Result<(CadDocument, usize), String> { +pub fn load_bytes_finalized(path: &Path, bytes: Vec) -> Result { let name = path .file_name() .map(|n| n.to_string_lossy().into_owned()) @@ -1006,8 +989,7 @@ pub fn load_bytes_finalized(path: &Path, bytes: Vec) -> Result<(CadDocument, doc.source_path = Some(path.to_string_lossy().into_owned()); // Opening is a field evaluation event (FIELDEVAL bit 1). crate::entities::field::update_fields(&mut doc, 1, None); - let dropped = purge_corrupt_entities(&mut doc); - Ok((doc, dropped)) + Ok(doc) } /// Load a DWG or DXF file directly from a path (auto-detect by extension). @@ -1254,7 +1236,6 @@ fn finalize_loaded_outcome( let doc = &mut outcome.document; normalize_block_origins(doc); materialize_missing_block_markers(doc); - normalize_knotless_splines(doc); if outcome.stats.source_format == Some(codec::SourceFormat::Dxf) { fix_dxf_dimension_rotations(doc); fix_dxf_layout_plot_settings(doc); @@ -2679,174 +2660,24 @@ fn sync_current_styles_on_save(doc: &mut CadDocument) { set_sketch_settings(doc, sketch_type, increment, tolerance); } -// ── Corrupt-entity guard ────────────────────────────────────────────────── -// -// opencadcodec's DWG parser occasionally desynchronises on certain files and -// produces entities with garbage fields: non-unit normals (components in -// 1e200+), nonsensical vertex counts (e.g. 100000), or infinite/NaN -// coordinates. Tessellating such entities triggers huge allocations and -// numerical blow-ups in the wire pipeline. -// -// `purge_corrupt_entities` scans the document and removes any entity that -// fails a cheap sanity check, returning the number dropped so the caller can -// surface it to the UI / log. -// -// Keep valid degenerate geometry: dropping it would trigger strict-open recovery. - -fn finite_unit_normal(n: &codec::types::Vector3) -> bool { - let (x, y, z) = (n.x, n.y, n.z); - if !x.is_finite() || !y.is_finite() || !z.is_finite() { - return false; +/// Recovery runs the codec's repair and reports what it did, and what it +/// left, through the drawing's notifications. +pub(crate) fn repair_drawing(doc: &mut CadDocument) { + let repair = doc.repair(); + for action in &repair.actions { + doc.notifications.notify( + codec::notification::NotificationType::Warning, + format!("Recovery repair: {action:?}"), + ); } - let mag2 = x * x + y * y + z * z; - // Accept anything within ~10% of unit length. Real files sometimes - // store slightly denormalised normals from rounding. - (mag2 - 1.0).abs() < 0.21 -} - -fn finite_coord(v: f64) -> bool { - v.is_finite() && v.abs() < 1.0e12 -} - -fn finite_vec3(v: &codec::types::Vector3) -> bool { - finite_coord(v.x) && finite_coord(v.y) && finite_coord(v.z) -} - -/// Returns true if the entity looks like parser garbage and should be dropped. -pub(crate) fn is_entity_corrupt(e: &EntityType) -> bool { - use codec::entities::EntityType as E; - // Reject polylines at or above this vertex count. Even valid drawings - // rarely use this many — and parser desync produces exactly-100_000-vertex - // junk records. - const MAX_VERTS: usize = 100_000; - match e { - E::LwPolyline(p) => { - !finite_unit_normal(&p.normal) - || p.vertices.len() >= MAX_VERTS - || !finite_coord(p.elevation) - || p.elevation.abs() > 1.0e10 - || !finite_coord(p.thickness) - || p.thickness.abs() > 1.0e10 - || p.vertices - .iter() - .any(|v| !finite_coord(v.location.x) || !finite_coord(v.location.y)) - } - E::Polyline2D(p) => { - !finite_unit_normal(&p.normal) - || p.vertices.len() >= MAX_VERTS - || !finite_coord(p.elevation) - || p.elevation.abs() > 1.0e10 - || !finite_coord(p.thickness) - || p.thickness.abs() > 1.0e10 - || p.vertices.iter().any(|v| !finite_vec3(&v.location)) - } - E::Polyline3D(p) => { - p.vertices.len() >= MAX_VERTS || p.vertices.iter().any(|v| !finite_vec3(&v.position)) - } - E::Polyline(p) => { - p.vertices.len() >= MAX_VERTS || p.vertices.iter().any(|v| !finite_vec3(&v.location)) - } - E::Line(l) => !finite_vec3(&l.start) || !finite_vec3(&l.end), - // Zero-radius curves are valid and have bounded kernel tessellation. - E::Circle(c) => { - !finite_vec3(&c.center) || !finite_coord(c.radius) || c.radius.abs() > 1.0e10 - } - E::Arc(a) => { - !finite_vec3(&a.center) - || !finite_coord(a.radius) - || !a.start_angle.is_finite() - || !a.end_angle.is_finite() - || a.radius.abs() > 1.0e10 - || !finite_unit_normal(&a.normal) - } - E::Ellipse(e) => { - !finite_vec3(&e.center) - || !finite_vec3(&e.major_axis) - || !e.start_parameter.is_finite() - || !e.end_parameter.is_finite() - || (e.end_parameter - e.start_parameter).abs() < 1.0e-9 - || { - let m2 = e.major_axis.x * e.major_axis.x - + e.major_axis.y * e.major_axis.y - + e.major_axis.z * e.major_axis.z; - !m2.is_finite() || m2 < 1.0e-20 || m2 > 1.0e20 - } - || !e.minor_axis_ratio.is_finite() - || e.minor_axis_ratio.abs() < 1.0e-10 - } - E::Spline(s) => { - // Parser desync emits exactly-100_000-control-point splines with a - // garbage knot vector. Building a NURBS from one and - // tessellating it runs `parameter_division` into an unbounded - // allocation — single-threaded, 32 GB+ — long before the drawing - // finishes loading. Reject the desync signature plus any spline - // the kernel can't build: non-finite control points, or a knot vector - // that's non-finite, non-monotonic, or the wrong length - // (the kernel requires `knots.len() == ctrl.len() + degree + 1`). - let n = s.control_points.len(); - let degree_bad = s.degree < 1; - let deg = s.degree.max(0) as usize; - let compact_periodic_knots = s.flags.periodic && s.knots.len() == n.saturating_add(1); - let knots_bad = !s.knots.is_empty() - && (s.knots.iter().any(|k| !k.is_finite()) - || s.knots.windows(2).any(|w| w[1] < w[0]) - || (!compact_periodic_knots && s.knots.len() != n + deg + 1)); - // A single control point with no knots and no fit points cannot - // form a curve, and no knot vector exists for it. - let lone_point = n == 1 && s.knots.is_empty() && s.fit_points.is_empty(); - n >= MAX_VERTS - || degree_bad - || lone_point - || s.control_points.iter().any(|p| !finite_vec3(p)) - || knots_bad - } - _ => false, + for issue in &repair.unresolved { + doc.notifications.notify( + codec::notification::NotificationType::Warning, + format!("Recovery left unresolved: {}", issue.message), + ); } } -/// Give control-point splines stored without knots a degree their control -/// points can carry, and the matching clamped knot vector. -/// -/// A degree-p curve needs at least p + 1 control points. Knot generation -/// (here, and in the DWG writer for knot-less splines) subtracts in `usize` -/// and underflows when there are fewer; in release builds the wrapped count -/// drives an unbounded allocation. Lowering the degree keeps the geometry the -/// points describe: two points are a straight segment at any degree. -fn normalize_knotless_splines(doc: &mut CadDocument) { - for entity in doc.entities_mut() { - let EntityType::Spline(spline) = entity else { - continue; - }; - let n = spline.control_points.len(); - if !spline.knots.is_empty() || n < 2 || spline.degree < 1 { - continue; - } - let degree = (spline.degree as usize).min(n - 1); - spline.degree = degree as i32; - spline.knots = codec::entities::Spline::generate_clamped_knots(degree, n); - } -} - -pub fn purge_corrupt_entities(doc: &mut CadDocument) -> usize { - use crate::par::prelude::*; - normalize_knotless_splines(doc); - // Detection is pure and read-only; the per-vertex finite/extent checks on - // large polylines dominate, so fan the scan out across cores. Gather - // entity references in one pass, test in parallel, then remove serially - // (`remove_entity` needs `&mut doc`). - let entities: Vec<&EntityType> = doc.entities().collect(); - let bad: Vec = entities - .par_iter() - .filter(|e| is_entity_corrupt(e)) - .map(|e| e.common().handle) - .collect(); - let n = bad.len(); - for h in bad { - doc.remove_entity(h); - } - n -} - /// opencadcodec's ViewportStatusFlags::from_bits() maps bit 0 → is_on and bit 15 → locked, /// but the real DXF/DWG spec uses bit 15 (0x8000) → viewport on and bit 14 (0x4000) → locked. /// Files from AutoCAD and other tools always set bit 15 for active viewports, leaving bit 0 @@ -2969,7 +2800,7 @@ mod dimension_arrow_save_tests { dimension.definition_point = Vector3::new(0.0, 20.0, 0.0); dimension.base.definition_point = dimension.definition_point; dimension.base.text_middle_point = Vector3::new(50.0, 20.0, 0.0); - doc.add_entity(EntityType::Dimension(Dimension::Linear(dimension))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))) .unwrap(); doc } @@ -3161,214 +2992,6 @@ mod layer_roundtrip_tests { } } -#[cfg(test)] -mod corrupt_guard_tests { - use super::*; - use codec::entities::{Arc, Circle, EntityType, Spline}; - use codec::types::Vector3; - - fn knotless_spline(degree: i32, points: usize) -> Spline { - let mut spline = Spline::new(); - spline.degree = degree; - spline.control_points = (0..points) - .map(|index| Vector3::new(index as f64, index as f64, 0.0)) - .collect(); - spline - } - - // Degree 3 over two control points with no knot vector: generating knots - // for it underflows, and writing it to DWG used to panic (debug) or - // allocate without bound (release). - #[test] - fn knotless_spline_with_too_few_points_is_lowered_and_saves_as_dwg() { - let mut doc = CadDocument::new(); - doc.add_entity(EntityType::Spline(knotless_spline(3, 2))) - .unwrap(); - doc.add_entity(EntityType::Spline(knotless_spline(3, 1))) - .unwrap(); - assert_eq!( - purge_corrupt_entities(&mut doc), - 1, - "the lone point is dropped" - ); - let spline = doc - .entities() - .find_map(|entity| match entity { - EntityType::Spline(spline) => Some(spline.clone()), - _ => None, - }) - .expect("the two-point spline is kept"); - assert_eq!(spline.degree, 1); - assert_eq!(spline.knots, vec![0.0, 0.0, 1.0, 1.0]); - - let path = - std::env::temp_dir().join(format!("ocs_knotless_spline_{}.dwg", std::process::id())); - save_as_version(&doc, &path, codec::DxfVersion::AC1032).expect("save"); - let _ = std::fs::remove_file(&path); - } - - // `load_file` (headless export, xrefs, block import) does not purge, so - // the spline repair has to happen when any load is finalized. - #[test] - fn knotless_spline_is_repaired_by_every_load_path() { - const DXF: &str = - "0\nSECTION\n2\nENTITIES\n0\nSPLINE\n8\n0\n70\n0\n71\n3\n72\n0\n73\n2\n74\n0\n\ -10\n0\n20\n0\n30\n0\n10\n1\n20\n1\n30\n0\n0\nENDSEC\n0\nEOF\n"; - let dir = std::env::temp_dir(); - let source = dir.join(format!("ocs_knotless_load_{}.dxf", std::process::id())); - let target = dir.join(format!("ocs_knotless_load_{}.dwg", std::process::id())); - std::fs::write(&source, DXF).unwrap(); - let doc = load_file(&source).expect("load"); - let _ = std::fs::remove_file(&source); - let spline = doc - .entities() - .find_map(|entity| match entity { - EntityType::Spline(spline) => Some(spline), - _ => None, - }) - .expect("spline"); - assert_eq!(spline.degree, 1); - assert_eq!(spline.knots.len(), 4); - save_as_version(&doc, &target, codec::DxfVersion::AC1032).expect("save"); - let _ = std::fs::remove_file(&target); - } - - // Small but finite arcs are valid records. Kernel tessellation is bounded, - // so opening must retain them instead of treating their size as corruption. - #[test] - fn keeps_small_finite_arc() { - let mut a = Arc::new(); - a.center = Vector3::new(2880.84, 891.83, 0.0); - a.radius = 0.0038974142851181423; - a.start_angle = 1.0401656235942365; - a.end_angle = 1.0401671831670538; - a.normal = Vector3::new(0.0, 0.0, 1.0); - assert!(!is_entity_corrupt(&EntityType::Arc(a))); - } - - // A nearly straight arc still carries valid source geometry. - #[test] - fn keeps_nearly_straight_arc() { - let mut a = Arc::new(); - a.center = Vector3::new(551435.3071786845, 4051623.7156955916, 0.0); - a.radius = 35.0; - a.start_angle = 5.823361856481176; - a.end_angle = 5.823362506017916; - a.normal = Vector3::new(0.0, 0.0, 1.0); - assert!(!is_entity_corrupt(&EntityType::Arc(a))); - } - - // A large-radius small-sweep arc is still a visible curve and must survive: - // radius 1e6 × sweep 1e-4 ≈ 100 units of arc. - #[test] - fn keeps_large_radius_small_sweep_arc() { - let mut a = Arc::new(); - a.radius = 1.0e6; - a.start_angle = 0.0; - a.end_angle = 1.0e-4; - a.normal = Vector3::new(0.0, 0.0, 1.0); - assert!(!is_entity_corrupt(&EntityType::Arc(a))); - } - - #[test] - fn keeps_zero_radius_circle_and_arc() { - let mut c = Circle::new(); - c.center = Vector3::new(206.2, 150.7, 0.0); - c.radius = 0.0; - assert!(!is_entity_corrupt(&EntityType::Circle(c))); - - let mut a = Arc::new(); - a.center = Vector3::new(223.5, 174.5, 0.0); - a.radius = 0.0; - a.start_angle = 0.0; - a.end_angle = 0.0; - a.normal = Vector3::new(0.0, 0.0, 1.0); - assert!(!is_entity_corrupt(&EntityType::Arc(a))); - } - - #[test] - fn drops_absurd_radius_circle() { - let mut c = Circle::new(); - c.radius = 1.0e11; - assert!(is_entity_corrupt(&EntityType::Circle(c))); - let mut c = Circle::new(); - c.radius = f64::NAN; - assert!(is_entity_corrupt(&EntityType::Circle(c))); - } - - // Parser desync emits 100_000-control-point splines; building a kernel - // NURBS from one and tessellating it OOMs. The control-point cap rejects it. - #[test] - fn rejects_desync_spline() { - let pts = vec![Vector3::new(0.0, 0.0, 0.0); 100_000]; - let s = Spline::from_control_points(3, pts); - assert!(is_entity_corrupt(&EntityType::Spline(s))); - } - - // A collapsed spline is still a valid source record. Kernel subdivision - // has a fixed depth bound and can process it safely. - #[test] - fn keeps_degenerate_point_spline() { - let pts = vec![Vector3::new(1e-12, -1e-12, 0.0); 9]; - let s = Spline::from_control_points(3, pts); - assert!(!is_entity_corrupt(&EntityType::Spline(s))); - } - - #[test] - fn keeps_compact_periodic_spline_knots() { - let pts = (0..12) - .map(|index| Vector3::new(index as f64, (index % 3) as f64, 0.0)) - .collect(); - let mut s = Spline::from_control_points(2, pts); - s.flags.closed = true; - s.flags.periodic = true; - s.knots = (0..13).map(|value| value as f64).collect(); - assert!(!is_entity_corrupt(&EntityType::Spline(s))); - } - - // A normal cubic spline (4 control points, valid clamped knots) survives. - #[test] - fn keeps_valid_spline() { - let pts = vec![ - Vector3::new(0.0, 0.0, 0.0), - Vector3::new(1.0, 1.0, 0.0), - Vector3::new(2.0, -1.0, 0.0), - Vector3::new(3.0, 0.0, 0.0), - ]; - let s = Spline::from_control_points(3, pts); - assert!(!is_entity_corrupt(&EntityType::Spline(s))); - } - - // A corrupt or adversarial MINSERT row/column pair (u16, so its unchecked - // product can reach into the billions) must be rejected before it can - // drive the render graph's per-instance allocation and expansion. - #[test] - fn preserves_large_minsert_data_while_rendering_is_bounded() { - let mut i = codec::entities::Insert::new("BLOCK", Vector3::ZERO); - i.row_count = u16::MAX; - i.column_count = u16::MAX; - assert!(!is_entity_corrupt(&EntityType::Insert(i))); - } - - // An ordinary array insert, well under the budget, is valid source data. - #[test] - fn keeps_a_reasonable_minsert() { - let mut i = codec::entities::Insert::new("BLOCK", Vector3::ZERO); - i.row_count = 10; - i.column_count = 10; - i.row_spacing = 5.0; - i.column_spacing = 5.0; - assert!(!is_entity_corrupt(&EntityType::Insert(i))); - } - - // A plain (non-array) INSERT is never treated as a MINSERT-count problem. - #[test] - fn keeps_a_plain_insert() { - let i = codec::entities::Insert::new("BLOCK", Vector3::ZERO); - assert!(!is_entity_corrupt(&EntityType::Insert(i))); - } -} - #[cfg(test)] mod pre_r2000_layer_plot_tests { use super::*; @@ -3545,11 +3168,12 @@ mod prepare_save_tests { dim.base.definition_point = Vector3::ZERO; dim.base.common.handle = doc.allocate_handle(); let handle = dim.base.common.handle; - doc.add_entity(EntityType::Dimension(Dimension::Linear(dim))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))) .unwrap(); let prepared = prepare_document_for_save(doc.clone(), doc.version); - let EntityType::Dimension(Dimension::Linear(linear)) = prepared.get_entity(handle).unwrap() + let Some(Dimension::Linear(linear)) = + crate::entities::dimension::as_dimension(prepared.get_entity(handle).unwrap()) else { panic!("dimension missing from prepared clone"); }; @@ -3565,7 +3189,9 @@ mod prepare_save_tests { assert_eq!(linear.base.definition_point, linear.definition_point); // The live document is untouched: no block name, stale group-10. - let EntityType::Dimension(Dimension::Linear(live)) = doc.get_entity(handle).unwrap() else { + let Some(Dimension::Linear(live)) = + crate::entities::dimension::as_dimension(doc.get_entity(handle).unwrap()) + else { panic!("dimension missing from live document"); }; assert!(live.base.block_name.is_empty()); @@ -3582,7 +3208,7 @@ mod prepare_save_tests { let mut dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); dim.base.common.handle = doc.allocate_handle(); - doc.add_entity(EntityType::Dimension(Dimension::Linear(dim))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))) .unwrap(); for ext in ["dwg", "dxf"] { let inline = save_to_bytes(&doc, ext, codec::DxfVersion::AC1032).expect("inline"); diff --git a/src/io/ole_embed.rs b/src/io/ole_embed.rs index c82e93cdc..29a87cec3 100644 --- a/src/io/ole_embed.rs +++ b/src/io/ole_embed.rs @@ -168,7 +168,7 @@ pub fn add_embedded_image( ) -> Result { let (upper_left, lower_right) = corners_from_placement(origin, width, image.aspect()); let ole = build_embedded_ole(image, upper_left, lower_right); - doc.add_entity(codec::EntityType::Ole2Frame(ole)) + doc.add_entity(codec::EntityType::Ole2Frame(Box::new(ole))) .map_err(|e| e.to_string()) } diff --git a/src/io/recovery.rs b/src/io/recovery.rs index 0b1ae1b4d..700033b02 100644 --- a/src/io/recovery.rs +++ b/src/io/recovery.rs @@ -24,8 +24,6 @@ pub struct RecoveryReport { pub source_sha256: Option, pub read_stats: Option, pub entities_scanned: usize, - pub entities_removed: usize, - pub referenced_entities_removed: usize, pub parser_errors_recovered: usize, pub diagnostics: Vec<(String, String)>, pub references_checked: usize, @@ -54,8 +52,6 @@ impl RecoveryReport { source_sha256: Option, read_stats: Option, entities_scanned: usize, - entities_removed: usize, - referenced_entities_removed: usize, references: &[XrefInfo], notifications: &codec::notification::NotificationCollection, save_as_required: bool, @@ -163,8 +159,6 @@ impl RecoveryReport { source_sha256, read_stats, entities_scanned, - entities_removed, - referenced_entities_removed, parser_errors_recovered, diagnostics, references_checked: references.len(), @@ -211,8 +205,6 @@ impl RecoveryReport { .unwrap_or(0), read_stats, entities_scanned: 0, - entities_removed: 0, - referenced_entities_removed: 0, diagnostics: Vec::new(), references_checked: 0, references_loaded: 0, @@ -233,17 +225,11 @@ impl RecoveryReport { } } - pub fn removed_total(&self) -> usize { - self.entities_removed - .saturating_add(self.referenced_entities_removed) - } - pub fn issues_found(&self) -> usize { self.parser_errors_recovered .saturating_add(self.references_recovered) .saturating_add(self.references_failed) .saturating_add(self.references_missing) - .saturating_add(self.removed_total()) .saturating_add(usize::from(self.error.is_some())) } @@ -315,11 +301,6 @@ impl RecoveryReport { )); } lines.push(format!("Entities scanned: {}", self.entities_scanned)); - lines.push(format!("Entities removed: {}", self.entities_removed)); - lines.push(format!( - "Referenced entities removed: {}", - self.referenced_entities_removed - )); lines.push(format!( "Parser errors recovered: {}", self.parser_errors_recovered diff --git a/src/io/xref.rs b/src/io/xref.rs index 541362102..6aade03b0 100644 --- a/src/io/xref.rs +++ b/src/io/xref.rs @@ -277,12 +277,8 @@ fn read_outcome_from_bytes( /// `base_dir`, and populate each xref block with entities from the /// referenced file. /// -/// Returns a list of [`XrefInfo`] describing each xref block found, plus the -/// number of corrupt xref entities dropped during merge. Purging happens -/// inline as each xref's entities are merged — xref content is parser output -/// just like the host doc, so it gets the same corrupt-entity guard. Folding -/// it in here avoids a second full-document `entities()` walk after resolve. -pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> (Vec, usize) { +/// Returns a list of [`XrefInfo`] describing each xref block found. +pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> Vec { resolve_xrefs_with_filter(doc, base_dir, None, None) } @@ -295,7 +291,7 @@ pub fn resolve_xrefs_for_keys( doc: &mut CadDocument, base_dir: &Path, keys: &HashSet, -) -> (Vec, usize) { +) -> Vec { resolve_xrefs_with_filter(doc, base_dir, None, Some(keys)) } @@ -308,7 +304,7 @@ pub fn resolve_xrefs_with_progress( doc: &mut CadDocument, base_dir: &Path, progress: Option>, -) -> (Vec, usize) { +) -> Vec { resolve_xrefs_with_filter(doc, base_dir, progress, None) } @@ -317,7 +313,7 @@ fn resolve_xrefs_with_filter( base_dir: &Path, progress: Option>, only: Option<&HashSet>, -) -> (Vec, usize) { +) -> Vec { // Auto-resolve every xref — frustum + LOD culling keep GPU cost bounded. let xref_entries: Vec<(String, String, Handle)> = doc .block_records @@ -432,7 +428,6 @@ fn resolve_xrefs_with_filter( // Phase 2 — merge each parsed xref into the host document, in the original // block order (par_iter preserves it), so handle allocation is deterministic. let mut result = Vec::with_capacity(parsed.len()); - let mut dropped = 0usize; #[allow(unused_mut, unused_variables)] for ( merge_index, @@ -468,19 +463,7 @@ fn resolve_xrefs_with_filter( .iter() .map(|diagnostic| diagnostic.message.clone()), ); - let invalid = super::purge_corrupt_entities(&mut outcome.document); - if invalid > 0 { - diagnostics.push(format!( - "normal read found {invalid} structurally invalid reference records" - )); - #[cfg(not(target_arch = "wasm32"))] - if source_sha256.is_none() { - source_sha256 = resolved.as_ref().and_then(|path| { - super::stable_sha256_file(path, initial_fingerprint.as_ref()) - }); - } - } - if recovered || invalid > 0 { + if recovered { (XrefStatus::Failed, diagnostics, Some(outcome.stats)) } else { // Reload is replacement, never append. Keep the prior merge @@ -502,7 +485,7 @@ fn resolve_xrefs_with_filter( let _ = unload_reference(doc, br_handle.value()); remove_pipe_symbols(doc, &block_name); ensure_block_entities(doc, &block_name); - dropped += merge_xref_into_block(doc, &block_name, br_handle, outcome.document); + merge_xref_into_block(doc, &block_name, br_handle, outcome.document); if visretain { restore_dependent_layers(doc, &block_name, kept_layers); } @@ -533,7 +516,7 @@ fn resolve_xrefs_with_filter( } } - (result, dropped) + result } /// Underlay files named by a relative (or moved) path: read them from where @@ -1218,13 +1201,12 @@ fn copy_xref_sortents( /// — which doesn't know about the xref's layers — and silently falls /// back to WHITE / 1 px line weight. AutoCAD's BIND command uses the /// same naming scheme. -/// Returns the number of corrupt entities skipped during the merge. fn merge_xref_into_block( doc: &mut CadDocument, xref_block_name: &str, br_handle: Handle, xref_doc: CadDocument, -) -> usize { +) { let prefix = xref_block_name; // Carry the xref's INSUNITS onto the host BlockRecord. Used at INSERT @@ -1264,7 +1246,7 @@ fn merge_xref_into_block( // ── Entities (shared helper) ──────────────────────────────────────── // The unremapped-handle count is ignored on the load path (BIND reports // it per bind). - let (dropped, _, entity_handle_map) = merge_source_entities(doc, &xref_doc, br_handle, &maps); + let (_, entity_handle_map) = merge_source_entities(doc, &xref_doc, br_handle, &maps); // ── Draw-order overrides (shared helper) ────────────────────────────── copy_xref_sortents( @@ -1274,7 +1256,6 @@ fn merge_xref_into_block( &maps.br_handles, &entity_handle_map, ); - dropped } /// Source entities in display order: each block record's `entity_handles` @@ -1308,26 +1289,18 @@ fn ordered_source_entities(xref_doc: &CadDocument) -> Vec<(Handle, EntityType)> /// Merge one source doc's entities into `target`, routing model-space content /// into `target_br` and nested-block content into its imported counterpart -/// (`maps.br_handles`). Returns corrupt-drop count, unremapped-handle count, -/// and the old→new entity handle map for the sortents copy. +/// (`maps.br_handles`). Returns the unremapped-handle count and the old→new +/// entity handle map for the sortents copy. fn merge_source_entities( target: &mut CadDocument, source: &CadDocument, target_br: Handle, maps: &XrefSymbolMaps, -) -> (usize, usize, HashMap) { +) -> (usize, HashMap) { let source_ms_handle = source.header.model_space_block_handle; let mut entity_handle_map: HashMap = HashMap::default(); - let mut dropped = 0usize; let mut unremapped = 0usize; for (old_h, mut entity) in ordered_source_entities(source) { - // Drop parser-garbage entities (bad normals / vertex counts / inf - // coords) before they enter the host doc — they trigger huge - // allocations and unbounded recursion in the wire pipeline. - if super::is_entity_corrupt(&entity) { - dropped += 1; - continue; - } // Remap every symbol reference so the host's resolver hits the copies // just imported (load path ignores the unremapped count; BIND reports // it per bind). @@ -1351,7 +1324,7 @@ fn merge_source_entities( entity_handle_map.insert(old_h, new_h); } } - (dropped, unremapped, entity_handle_map) + (unremapped, entity_handle_map) } fn is_sentinel_linetype(name: &str) -> bool { @@ -2170,8 +2143,7 @@ fn merge_bound_doc( taken, }; let maps = import_xref_symbols(target, source, &mut naming); - let (_, unremapped, entity_handle_map) = - merge_source_entities(target, source, target_br, &maps); + let (unremapped, entity_handle_map) = merge_source_entities(target, source, target_br, &maps); copy_xref_sortents( target, source, @@ -2970,7 +2942,7 @@ mod tests { // 3. Targeted reload: back to Loaded. let mut handles = HashSet::default(); handles.insert(doc.block_records.get("MID").unwrap().handle); - let (infos, _) = resolve_xrefs_for_keys(&mut doc, &dir, &handles); + let infos = resolve_xrefs_for_keys(&mut doc, &dir, &handles); assert!(infos.iter().any(|i| i.name == "MID")); let listed = collect_entries_with_prev(&doc, &dir, &empty, &no_prev); assert!(listed @@ -3336,7 +3308,7 @@ mod tests { // Hatch (pattern names have no table — preserved verbatim). let mut hatch = codec::entities::Hatch::new(); hatch.pattern.name = "ANSI31".to_string(); - doc.add_entity(codec::EntityType::Hatch(hatch)).unwrap(); + doc.add_entity(codec::EntityType::Hatch(Box::new(hatch))).unwrap(); // Dim-style reference via a tolerance entity. doc.dim_styles .add(codec::tables::DimStyle::new("ARCH")) diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 863ec5bfb..cb010ab6a 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -696,10 +696,10 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "ATTSYNC block name to sync:" => Some(("insert", "attsync-block-name-to-sync")), "ATTSYNC: no block named \"{arg}\"." => Some(("insert", "attsync-no-block-named-arg")), "ATTSYNC: synchronised {synced} insert(s) of \"{block}\" against {} attribute definition(s)." => Some(("insert", "attsync-synchronised-synced-insert-s-of-block")), + "AUDIT Fix any errors detected? [Yes / No] :" => Some(("styles", "audit-fix-any-errors-detected")), "AUDIT: no issues found." => Some(("styles", "audit-no-issues-found")), - "AUDIT: reference(s) to undefined block(s): {}" => Some(("styles", "audit-reference-s-to-undefined-block-s")), - "AUDIT: reference(s) to undefined layer(s): {}" => Some(("styles", "audit-reference-s-to-undefined-layer-s")), - "AUDIT: report only — no automatic repair performed." => Some(("styles", "audit-report-only-no-automatic-repair-performe")), + "AUDIT: {} error(s), {} warning(s) found." => Some(("styles", "audit-error-s-warning-s-found")), + "AUDIT: {} repair(s) applied, {} issue(s) left unresolved." => Some(("styles", "audit-repair-s-applied-issue-s-left")), "AUDIT: scanned {total} object(s)." => Some(("styles", "audit-scanned-total-object-s")), "About" => Some(("manage", "about")), "Above" => Some(("common", "above")), @@ -3806,8 +3806,6 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "WIPEOUT Rectangular Specify first corner:" => Some(("draw", "wipeout-rectangular-specify-first-corner")), "WIPEOUT Rectangular Specify opposite corner:" => Some(("draw", "wipeout-rectangular-specify-opposite-corner")), "Warning" => Some(("errors", "warning")), - "Warning: {} corrupt entities dropped (parser junk — bad normals / counts)" => Some(("file", "warning-corrupt-entities-dropped-parser-junk-b")), - "Warning: {} corrupt xref entities dropped" => Some(("file", "warning-corrupt-xref-entities-dropped")), "Watertight" => Some(("properties", "watertight")), "Web" => Some(("common", "web")), "Web File" => Some(("properties", "web-file")), diff --git a/src/modules/annotate/aligned_dim.rs b/src/modules/annotate/aligned_dim.rs index ea0e326d6..5d62c941e 100644 --- a/src/modules/annotate/aligned_dim.rs +++ b/src/modules/annotate/aligned_dim.rs @@ -95,7 +95,7 @@ pub(crate) fn aligned_dimension_entity( crate::entities::dimension::reset_automatic_text_position(&mut dim.base); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override); - EntityType::Dimension(Dimension::Aligned(dim)) + EntityType::Dimension(Box::new(Dimension::Aligned(dim))) } impl CadCommand for AlignedDimensionCommand { diff --git a/src/modules/annotate/angular_dim.rs b/src/modules/annotate/angular_dim.rs index e101214fd..309d379e0 100644 --- a/src/modules/annotate/angular_dim.rs +++ b/src/modules/annotate/angular_dim.rs @@ -232,7 +232,7 @@ impl AngularDimensionCommand { } fn commit(&self, dimension: Dimension) -> CmdResult { - let entity = self.plane.place_entity(EntityType::Dimension(dimension)); + let entity = self.plane.place_entity(EntityType::Dimension(Box::new(dimension))); CmdResult::CommitDimension { entity, association: DimensionAssociationInput::Explicit(self.source_refs.clone()), @@ -1242,7 +1242,7 @@ pub(crate) fn angular_two_line_entity( dim.base.insertion_point = dim.dimension_arc; dim.base.actual_measurement = dim.measurement_degrees(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Angular2Ln(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Angular2Ln(dim)))) } /// A three-point angular dimension (vertex, two points, arc point), for a @@ -1261,7 +1261,7 @@ pub(crate) fn angular_three_point_entity( dim.base.insertion_point = dim.definition_point; dim.base.actual_measurement = dim.measurement_degrees(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Angular3Pt(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Angular3Pt(dim)))) } fn v3(point: DVec3) -> Vector3 { diff --git a/src/modules/annotate/arc_length_dim.rs b/src/modules/annotate/arc_length_dim.rs index 7dcfc758e..bd2476b9a 100644 --- a/src/modules/annotate/arc_length_dim.rs +++ b/src/modules/annotate/arc_length_dim.rs @@ -258,7 +258,7 @@ impl ArcLengthDimensionCommand { |handle| DimensionAssociationInput::Explicit(selection.association_sources(handle)), ); CmdResult::CommitDimension { - entity: plane.place_entity(EntityType::Dimension(Dimension::Arc(dimension))), + entity: plane.place_entity(EntityType::Dimension(Box::new(Dimension::Arc(dimension)))), association, preserve_base_style: false, continue_command: false, diff --git a/src/modules/annotate/diameter_dim.rs b/src/modules/annotate/diameter_dim.rs index 800370674..1dad74115 100644 --- a/src/modules/annotate/diameter_dim.rs +++ b/src/modules/annotate/diameter_dim.rs @@ -83,7 +83,7 @@ impl DiameterDimensionCommand { if let Some(angle) = self.text_angle { dim.base.text_rotation = angle; } - plane.place_entity(EntityType::Dimension(Dimension::Diameter(dim))) + plane.place_entity(EntityType::Dimension(Box::new(Dimension::Diameter(dim)))) } } @@ -103,7 +103,7 @@ pub(crate) fn diameter_constraint_entity( dim.leader_length = chord.distance(location).max(radius * 0.5); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Diameter(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Diameter(dim)))) } impl CadCommand for DiameterDimensionCommand { diff --git a/src/modules/annotate/dim_baseline.rs b/src/modules/annotate/dim_baseline.rs index 23612384c..4d2e862e8 100644 --- a/src/modules/annotate/dim_baseline.rs +++ b/src/modules/annotate/dim_baseline.rs @@ -151,7 +151,7 @@ impl DimBaselineCommand { let increment = self.effective_increment(&style.style_name); let plane = plane_from_normal(dimension.base().definition_point, style.normal); let pick = pick.and_then(|point| plane.project(point.to_array()).map(Vec2::from)); - let kind = match dimension { + let kind = match &**dimension { Dimension::Linear(source) => { let first = project(&plane, source.first_point); let second = project(&plane, source.second_point); @@ -441,7 +441,7 @@ impl CadCommand for DimBaselineCommand { self.committed += 1; self.advance(1.0); CmdResult::CommitDimension { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), association: DimensionAssociationInput::Infer(None), preserve_base_style: self.preserve_base_style, continue_command: true, @@ -489,7 +489,7 @@ impl CadCommand for DimBaselineCommand { fn dimension_preview(&self, cursor: DVec3) -> Option> { self.build_dimension(cursor).map(|dimension| { vec![DimensionPreview { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), preserve_base_style: self.preserve_base_style, }] }) diff --git a/src/modules/annotate/dim_continue.rs b/src/modules/annotate/dim_continue.rs index 8922e019b..1496f956d 100644 --- a/src/modules/annotate/dim_continue.rs +++ b/src/modules/annotate/dim_continue.rs @@ -117,7 +117,7 @@ impl DimContinueCommand { let style = SourceStyle::from_base(dimension.base()); let plane = plane_from_normal(dimension.base().definition_point, style.normal); let pick = pick_world.and_then(|point| plane.project(point.to_array()).map(Vec2::from)); - let kind = match dimension { + let kind = match &**dimension { Dimension::Linear(source) => { let rotation = source.rotation; let perpendicular = Vec2::new(-rotation.sin(), rotation.cos()); @@ -383,7 +383,7 @@ impl CadCommand for DimContinueCommand { } self.advance(point); CmdResult::CommitDimension { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), association: DimensionAssociationInput::Infer(None), preserve_base_style: self.preserve_base_style, continue_command: true, @@ -433,7 +433,7 @@ impl CadCommand for DimContinueCommand { fn dimension_preview(&self, cursor: DVec3) -> Option> { self.build_dimension(cursor).map(|dimension| { vec![DimensionPreview { - entity: EntityType::Dimension(dimension), + entity: EntityType::Dimension(Box::new(dimension)), preserve_base_style: self.preserve_base_style, }] }) diff --git a/src/modules/annotate/dimjogline.rs b/src/modules/annotate/dimjogline.rs index a80260e16..b63527637 100644 --- a/src/modules/annotate/dimjogline.rs +++ b/src/modules/annotate/dimjogline.rs @@ -145,13 +145,17 @@ impl CadCommand for DimJogLineCommand { } fn on_entity_pick(&mut self, handle: Handle, _point: DVec3) -> CmdResult { - let Some(EntityType::Dimension(dimension @ (Dimension::Linear(_) | Dimension::Aligned(_)))) = - self.picked_entity.take() - else { + let Some(EntityType::Dimension(dimension)) = self.picked_entity.take() else { return CmdResult::ReportError( t!("DIMJOGLINE: select a linear or aligned dimension.").into_owned(), ); }; + let dimension = *dimension; + if !matches!(dimension, Dimension::Linear(_) | Dimension::Aligned(_)) { + return CmdResult::ReportError( + t!("DIMJOGLINE: select a linear or aligned dimension.").into_owned(), + ); + } if handle.is_null() { return CmdResult::NeedPoint; } diff --git a/src/modules/annotate/dimspace.rs b/src/modules/annotate/dimspace.rs index ef0ef9e64..8c5959ff8 100644 --- a/src/modules/annotate/dimspace.rs +++ b/src/modules/annotate/dimspace.rs @@ -104,8 +104,8 @@ impl CadCommand for DimSpaceCommand { for selected in entities { if selected.handle != *base && matches!( - selected.entity, - EntityType::Dimension( + crate::entities::dimension::as_dimension(&selected.entity), + Some( codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) ) @@ -124,11 +124,14 @@ impl CadCommand for DimSpaceCommand { match &mut self.step { Step::PickBase => { if !matches!( - self.picked_entity.take(), - Some(EntityType::Dimension( + self.picked_entity + .take() + .as_ref() + .and_then(crate::entities::dimension::as_dimension), + Some( codec::entities::Dimension::Linear(_) | codec::entities::Dimension::Aligned(_) - )) + ) ) { return CmdResult::ReportError( t!("DIMSPACE: select a linear or aligned dimension.").into_owned(), diff --git a/src/modules/annotate/field_cmd.rs b/src/modules/annotate/field_cmd.rs index 7ab6a2920..6d24ae657 100644 --- a/src/modules/annotate/field_cmd.rs +++ b/src/modules/annotate/field_cmd.rs @@ -158,7 +158,7 @@ impl CadCommand for FieldPlaceCommand { mtext.attachment_point = self.attachment; // No defined width: the field text never wraps. mtext.rectangle_width = 0.0; - CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(mtext))) + CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(Box::new(mtext)))) } fn on_enter(&mut self) -> CmdResult { diff --git a/src/modules/annotate/jogged_radius_dim.rs b/src/modules/annotate/jogged_radius_dim.rs index f566d5bf8..fe43b88bb 100644 --- a/src/modules/annotate/jogged_radius_dim.rs +++ b/src/modules/annotate/jogged_radius_dim.rs @@ -138,7 +138,9 @@ impl JoggedRadiusDimensionCommand { ); CmdResult::CommitDimension { - entity: plane.place_entity(EntityType::Dimension(Dimension::LargeRadial(dimension))), + entity: plane.place_entity(EntityType::Dimension(Box::new(Dimension::LargeRadial( + dimension, + )))), association, preserve_base_style: false, continue_command: false, diff --git a/src/modules/annotate/leader_cmd.rs b/src/modules/annotate/leader_cmd.rs index 654c7c281..6f03e83f1 100644 --- a/src/modules/annotate/leader_cmd.rs +++ b/src/modules/annotate/leader_cmd.rs @@ -151,7 +151,7 @@ impl LeaderCommand { CmdResult::CommitManyAndEditText { entities: vec![ self.plane.place_entity(EntityType::Leader(leader)), - self.plane.place_entity(EntityType::MText(mtext)), + self.plane.place_entity(EntityType::MText(Box::new(mtext))), ], edit_index: 1, open_editor, diff --git a/src/modules/annotate/linear_dim.rs b/src/modules/annotate/linear_dim.rs index c997067cd..ee365950e 100644 --- a/src/modules/annotate/linear_dim.rs +++ b/src/modules/annotate/linear_dim.rs @@ -141,7 +141,7 @@ pub(crate) fn linear_dimension_entity( crate::entities::dimension::reset_automatic_text_position(&mut dim.base); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text_override); - EntityType::Dimension(Dimension::Linear(dim)) + EntityType::Dimension(Box::new(Dimension::Linear(dim))) } impl CadCommand for LinearDimensionCommand { diff --git a/src/modules/annotate/mleader_cmd.rs b/src/modules/annotate/mleader_cmd.rs index 81eef14ea..c1cc4cab8 100644 --- a/src/modules/annotate/mleader_cmd.rs +++ b/src/modules/annotate/mleader_cmd.rs @@ -648,7 +648,7 @@ impl CadCommand for MLeaderCommand { text.insertion_point.z, )); self.text = text.value.clone(); - self.selected_mtext = Some(text); + self.selected_mtext = Some(*text); self.content_type = LeaderContentType::MText; self.order = CreationOrder::ContentFirst; self.step = Step::PickPoints; diff --git a/src/modules/annotate/ordinate_dim.rs b/src/modules/annotate/ordinate_dim.rs index 0aa9ddb48..b8dff08b5 100644 --- a/src/modules/annotate/ordinate_dim.rs +++ b/src/modules/annotate/ordinate_dim.rs @@ -80,7 +80,7 @@ impl OrdinateDimCommand { } dim.refresh_measurement(); self.plane - .place_entity(EntityType::Dimension(Dimension::Ordinate(dim))) + .place_entity(EntityType::Dimension(Box::new(Dimension::Ordinate(dim)))) } } diff --git a/src/modules/annotate/qdim.rs b/src/modules/annotate/qdim.rs index 3f1f2357a..e60029e5c 100644 --- a/src/modules/annotate/qdim.rs +++ b/src/modules/annotate/qdim.rs @@ -341,7 +341,7 @@ impl QdimCommand { ]); ( self.plane - .place_entity(EntityType::Dimension(Dimension::Linear(dimension))), + .place_entity(EntityType::Dimension(Box::new(Dimension::Linear(dimension)))), association, ) } @@ -366,7 +366,7 @@ impl QdimCommand { dimension.refresh_measurement(); ( self.plane - .place_entity(EntityType::Dimension(Dimension::Ordinate(dimension))), + .place_entity(EntityType::Dimension(Box::new(Dimension::Ordinate(dimension)))), DimensionAssociationInput::Explicit(vec![point.sources.first().copied()]), ) } @@ -405,7 +405,7 @@ impl QdimCommand { dimension.base.text_user_positioned = true; dimension.leader_length = chord.distance(text); dimension.base.actual_measurement = dimension.measurement(); - EntityType::Dimension(Dimension::Radius(dimension)) + EntityType::Dimension(Box::new(Dimension::Radius(dimension))) } else { let opposite = center - direction * radius; let mut dimension = DimensionDiameter::new(v3(chord), v3(opposite)); @@ -415,7 +415,7 @@ impl QdimCommand { dimension.base.text_user_positioned = true; dimension.leader_length = chord.distance(text); dimension.base.actual_measurement = dimension.measurement(); - EntityType::Dimension(Dimension::Diameter(dimension)) + EntityType::Dimension(Box::new(Dimension::Diameter(dimension))) }; (self.plane.place_entity(entity), association) }) @@ -680,7 +680,7 @@ fn preview_entity(index: usize, entity: &EntityType) -> Vec { return Vec::new(); }; let mut lines: Vec> = Vec::new(); - match dimension { + match &**dimension { Dimension::Linear(value) => { let first = d3(value.first_point); let second = d3(value.second_point); diff --git a/src/modules/annotate/radius_dim.rs b/src/modules/annotate/radius_dim.rs index 435ae9277..7a8d79f93 100644 --- a/src/modules/annotate/radius_dim.rs +++ b/src/modules/annotate/radius_dim.rs @@ -93,7 +93,7 @@ pub(crate) fn radial_dimension_entity( if let Some(angle) = text_angle { dim.base.text_rotation = angle; } - plane.place_entity(EntityType::Dimension(Dimension::Radius(dim))) + plane.place_entity(EntityType::Dimension(Box::new(Dimension::Radius(dim)))) } /// A radius dimension for a dimensional constraint: the leader leaves the @@ -111,7 +111,7 @@ pub(crate) fn radius_constraint_entity( dim.leader_length = chord.distance(location).max(radius * 0.5); dim.base.actual_measurement = dim.measurement(); crate::entities::dimension::set_dimension_text_override(&mut dim.base, text); - Some(EntityType::Dimension(Dimension::Radius(dim))) + Some(EntityType::Dimension(Box::new(Dimension::Radius(dim)))) } /// The unit direction a radial constraint's dimension points in, from the diff --git a/src/modules/annotate/txt2mtxt.rs b/src/modules/annotate/txt2mtxt.rs index c0970a8aa..bd55200be 100644 --- a/src/modules/annotate/txt2mtxt.rs +++ b/src/modules/annotate/txt2mtxt.rs @@ -222,7 +222,7 @@ fn separate(p: &Piece, doc: &CadDocument) -> Vec { let at = p.point(p.rect[0] + x * (p.rect[1] - p.rect[0]), p.rect[3]); let mut m = mtext_from(p.entity, p.content.clone(), at, p.height, p.rotation); m.attachment_point = attachment; - vec![EntityType::MText(m)] + vec![EntityType::MText(Box::new(m))] } EntityType::MText(m) => { // The drawn words, grouped into lines by their baseline. @@ -261,7 +261,8 @@ fn separate(p: &Piece, doc: &CadDocument) -> Vec { .collect::>() .join(" "); let at = p.point(line[0].0 - origin_along, p.rect[3] - k as f64 * step); - EntityType::MText(mtext_from(p.entity, value, at, line[0].1.height, m.rotation)) + let height = line[0].1.height; + EntityType::MText(Box::new(mtext_from(p.entity, value, at, height, m.rotation))) }) .collect() } @@ -352,7 +353,7 @@ pub fn plan( } Some(Txt2MtxtPlan { erase: pieces.iter().map(|p| p.handle).collect(), - add: vec![EntityType::MText(m)], + add: vec![EntityType::MText(Box::new(m))], }) } diff --git a/src/modules/draw/clipboard/pastespec.rs b/src/modules/draw/clipboard/pastespec.rs index cbbefc93f..cc770ed7b 100644 --- a/src/modules/draw/clipboard/pastespec.rs +++ b/src/modules/draw/clipboard/pastespec.rs @@ -113,7 +113,7 @@ impl CadCommand for PasteSpecCommand { mtext.style = self.style.clone(); mtext.attachment_point = AttachmentPoint::TopLeft; mtext.rectangle_width = 0.0; - CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(mtext))) + CmdResult::CommitAndExit(self.plane.place_entity(EntityType::MText(Box::new(mtext)))) } fn on_enter(&mut self) -> CmdResult { diff --git a/src/modules/draw/draw/hatchedit.rs b/src/modules/draw/draw/hatchedit.rs index e05a26400..8acb6989d 100644 --- a/src/modules/draw/draw/hatchedit.rs +++ b/src/modules/draw/draw/hatchedit.rs @@ -925,7 +925,7 @@ mod tests { })); } hatch.paths.push(path); - let entity = EntityType::Hatch(hatch); + let entity = EntityType::Hatch(Box::new(hatch)); HatcheditCommand::with_handle(Handle::new(7), "ANSI31".into(), 1.0, 0.0, false) .with_appearance(Some(&entity), Color::Index(6), Transparency::T_40) .with_origin([9.0, 8.0]) @@ -1096,7 +1096,7 @@ mod tests { counter_clockwise: true, })); hatch.paths.push(path); - let entity = EntityType::Hatch(hatch); + let entity = EntityType::Hatch(Box::new(hatch)); let mut command = HatcheditCommand::with_handle(Handle::new(7), "ANSI31".into(), 1.0, 0.0, false) .with_appearance(Some(&entity), Color::ByLayer, Transparency::ByLayer); diff --git a/src/modules/draw/draw/raster_image.rs b/src/modules/draw/draw/raster_image.rs index 27b10c863..da1015837 100644 --- a/src/modules/draw/draw/raster_image.rs +++ b/src/modules/draw/draw/raster_image.rs @@ -104,7 +104,7 @@ impl ImageCommand { let (upper_left, lower_right) = corners_from_placement(ins, world_width, self.aspect()); let ole = build_embedded_ole(image, upper_left, lower_right); - self.plane.place_entity(EntityType::Ole2Frame(ole)) + self.plane.place_entity(EntityType::Ole2Frame(Box::new(ole))) } } } diff --git a/src/modules/draw/modify/explode.rs b/src/modules/draw/modify/explode.rs index 441909933..9e3c7c158 100644 --- a/src/modules/draw/modify/explode.rs +++ b/src/modules/draw/modify/explode.rs @@ -1439,7 +1439,7 @@ fn sync_dimension_base_points_and_collect_pending(doc: &mut CadDocument) -> Vec< let EntityType::Dimension(dimension) = entity else { return None; }; - let definition_point = match dimension { + let definition_point = match &**dimension { Dimension::Linear(value) => Some(value.definition_point), Dimension::Aligned(value) => Some(value.definition_point), Dimension::Radius(value) => Some(value.definition_point), @@ -1493,7 +1493,7 @@ pub fn bake_dimension_blocks(doc: &mut CadDocument) { let dimensions: Vec<(Handle, Dimension)> = pending .into_iter() .filter_map(|handle| match doc.get_entity(handle) { - Some(EntityType::Dimension(d)) => Some((handle, d.clone())), + Some(EntityType::Dimension(d)) => Some((handle, (**d).clone())), _ => None, }) .collect(); @@ -1654,7 +1654,7 @@ mod tests { d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); // block_name is left empty — exactly what OCS-created dimensions carry. let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); @@ -1693,7 +1693,7 @@ mod tests { // Exactly what OCS-created dimensions carry: insertion == text anchor. d.base.insertion_point = d.base.text_middle_point; let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); @@ -1720,7 +1720,7 @@ mod tests { d.definition_point = Vector3::new(0.0, 5.0, 0.0); d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); @@ -1798,7 +1798,7 @@ mod tests { d.rotation = 0.0; d.definition_point = Vector3::new(0.0, 8.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1827,7 +1827,7 @@ mod tests { let mut d = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); d.definition_point = Vector3::new(0.0, 5.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1875,7 +1875,7 @@ mod tests { .collect(); assert!(!expected.is_empty(), "the dimension explodes into no lines"); - let mut turned = EntityType::Dimension(flat); + let mut turned = EntityType::Dimension(Box::new(flat)); crate::scene::view::dispatch::apply_transform( &mut turned, &EntityTransform::Rotate { @@ -1911,7 +1911,7 @@ mod tests { ); d.definition_point = Vector3::new(5.0, 5.0, 0.0); // arc location let handle = doc - .add_entity(EntityType::Dimension(Dimension::Angular3Pt(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Angular3Pt(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1940,7 +1940,7 @@ mod tests { let mut d = DimensionDiameter::new(edge, far); d.base.text_middle_point = Vector3::new(3.0, 9.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Diameter(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Diameter(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -1971,7 +1971,7 @@ mod tests { d.rotation = std::f64::consts::FRAC_PI_2; // 90°, vertical dimension line d.definition_point = Vector3::new(8.0, 0.0, 0.0); let handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); let name = match doc.get_entity(handle) { @@ -2064,7 +2064,7 @@ mod tests { DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); d.definition_point = Vector3::new(0.0, 5.0, 0.0); d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); - doc.add_entity(EntityType::Dimension(Dimension::Linear(d))) + doc.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); let path = @@ -2171,7 +2171,7 @@ mod tests { d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); d.base.common.xdictionary_handle = Some(dict_handle); let dim_handle = doc - .add_entity(EntityType::Dimension(Dimension::Linear(d))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Linear(d)))) .unwrap(); bake_dimension_blocks(&mut doc); diff --git a/src/modules/insert/dgn_import.rs b/src/modules/insert/dgn_import.rs index 118ed7d8b..f93da2733 100644 --- a/src/modules/insert/dgn_import.rs +++ b/src/modules/insert/dgn_import.rs @@ -462,7 +462,7 @@ fn mtext_of_text(geom: &DgnGeom, color: u16) -> Option { m.rectangle_width = 0.0; m.drawing_direction = DrawingDirection::ByStyle; m.style = "Standard".to_string(); - Some(EntityType::MText(m)) + Some(EntityType::MText(Box::new(m))) } /// A text node as one MTEXT, a paragraph a line, attached at the node's @@ -515,7 +515,7 @@ fn mtext_of_node( m.rectangle_width = 0.0; m.drawing_direction = DrawingDirection::ByStyle; m.style = style; - Some(EntityType::MText(m)) + Some(EntityType::MText(Box::new(m))) } /// An arc, circle or ellipse in its own plane. diff --git a/src/modules/insert/pdf_import.rs b/src/modules/insert/pdf_import.rs index b8eb3c2bd..2c82251a5 100644 --- a/src/modules/insert/pdf_import.rs +++ b/src/modules/insert/pdf_import.rs @@ -1482,7 +1482,7 @@ pub fn convert( let layer = naming.layer(pdf_layer, Kind::Text); mtext.common.color = color_on(&layer, color_of(text.color)); mtext.common.layer = layer; - result.entities.push(EntityType::MText(mtext)); + result.entities.push(EntityType::MText(Box::new(mtext))); } } @@ -1712,7 +1712,7 @@ fn fill_entities( return Vec::new(); } hatch.elevation = z; - vec![EntityType::Hatch(hatch)] + vec![EntityType::Hatch(Box::new(hatch))] } inventory::submit!(crate::command::CommandRegistration { diff --git a/src/modules/layout/mvsetup.rs b/src/modules/layout/mvsetup.rs index 40b858ff1..50de2d2fb 100644 --- a/src/modules/layout/mvsetup.rs +++ b/src/modules/layout/mvsetup.rs @@ -144,7 +144,7 @@ impl MvsetupCommand { if self.arrangement == Arrangement::Engineering { viewport.view_direction = directions[(row * 2 + column) as usize].clone(); } - viewports.push(EntityType::Viewport(viewport)); + viewports.push(EntityType::Viewport(Box::new(viewport))); } } CmdResult::CommitEntitiesAndExit(viewports) diff --git a/src/scene/annotative.rs b/src/scene/annotative.rs index 9d1decb69..c7b287b29 100644 --- a/src/scene/annotative.rs +++ b/src/scene/annotative.rs @@ -322,7 +322,7 @@ pub fn supports_annotation_context(entity: &EntityType) -> bool { | EntityType::Tolerance(_) | EntityType::Hatch(_) => true, EntityType::Dimension(dimension) => { - !matches!(dimension, codec::entities::Dimension::Arc(_)) + !matches!(&**dimension, codec::entities::Dimension::Arc(_)) } _ => false, } diff --git a/src/scene/block_service.rs b/src/scene/block_service.rs index 5b20152d2..541321358 100644 --- a/src/scene/block_service.rs +++ b/src/scene/block_service.rs @@ -788,7 +788,7 @@ mod tests { dimension.base.block_name = "SVC_TARGET".to_string(); scene .document - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))) .unwrap(); // A table's picture block and a block-valued cell, by handle. @@ -894,7 +894,7 @@ mod tests { dimension.base.block_name = "SVC_RENAMED".to_string(); scene .document - .add_entity(EntityType::Dimension(Dimension::Aligned(dimension))) + .add_entity(EntityType::Dimension(Box::new(Dimension::Aligned(dimension)))) .unwrap(); let mut style = DimStyle::new("SVC_STYLE"); style.dimblk = target; diff --git a/src/scene/cache/block_cache.rs b/src/scene/cache/block_cache.rs index 11897898d..cf0214220 100644 --- a/src/scene/cache/block_cache.rs +++ b/src/scene/cache/block_cache.rs @@ -747,7 +747,7 @@ fn tessellate_sub_local( // Sanity guard: skip sub-entities whose primary dimension is so large // that adaptive tessellation will explode into hundreds of millions // of points. These are typically corrupt-radius primitives that slipped - // past purge_corrupt_entities (finite but absurd values). + // past the codec's unusable-geometry audit (finite but absurd values). if is_unreasonable_extent(sub) { return vec![]; } diff --git a/src/scene/camera_ops.rs b/src/scene/camera_ops.rs index 62d728ded..179e4261b 100644 --- a/src/scene/camera_ops.rs +++ b/src/scene/camera_ops.rs @@ -479,7 +479,7 @@ impl Scene { self.previous_view = Some(ViewSnapshot::Floating { layout, handle, - viewport: Box::new(viewport.clone()), + viewport: viewport.clone(), }); return; } @@ -538,7 +538,7 @@ impl Scene { }); return false; } - let current = Box::new(current.clone()); + let current = current.clone(); if let Some(EntityType::Viewport(destination)) = self.document.get_entity_mut(handle) { diff --git a/src/scene/dimension_assoc.rs b/src/scene/dimension_assoc.rs index bbb40ae90..f6394d49e 100644 --- a/src/scene/dimension_assoc.rs +++ b/src/scene/dimension_assoc.rs @@ -869,7 +869,7 @@ pub(crate) fn constraint_from_associative_dimension( Some(ParametricRef::whole(*reference.xrefs.first()?)) }; let measurement = DrivingValue::Literal(dimension.measurement()); - match dimension { + match &**dimension { Dimension::Aligned(_) => Some(( ConstraintKind::Distance, vec![point(0)?, point(1)?], @@ -921,7 +921,7 @@ pub(crate) fn radial_extension_points( let EntityType::Dimension(dimension_entity) = document.get_entity(dimension)? else { return None; }; - let target_point = match dimension_entity { + let target_point = match &**dimension_entity { Dimension::Radius(radius) => radius.definition_point, Dimension::Diameter(diameter) => diameter.angle_vertex, Dimension::LargeRadial(radial) => radial.chord_point, @@ -1009,7 +1009,7 @@ impl Scene { else { return; }; - let radial_data = match dimension_entity { + let radial_data = match &**dimension_entity { Dimension::Radius(radius) => Some(( radius.angle_vertex, radius.measurement(), @@ -1223,7 +1223,7 @@ impl Scene { }; // Radial references identify a circle/arc and angle, rather than a vertex. let radial_dimension = matches!( - dimension_entity, + &**dimension_entity, Dimension::Radius(_) | Dimension::Diameter(_) | Dimension::LargeRadial(_) ); if radial_dimension { @@ -1383,7 +1383,7 @@ impl Scene { let Some(EntityType::Dimension(entity)) = self.document.get_entity(dimension) else { return Vec::new(); }; - match entity { + match &**entity { // A radial dimension's single reference describes the point where // the leader meets the circle. Dimension::Radius(radius) => vec![radius.definition_point], @@ -1458,17 +1458,15 @@ impl Scene { let measurement_supported = !association.trans_space || self.document.get_entity(dimension).is_some_and(|entity| { matches!( - entity, - EntityType::Dimension(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) + crate::entities::dimension::as_dimension(entity), + Some(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) ) || persisted_measurement_scale(&self.document, entity).is_some() }); let measurement_supported = measurement_supported && self.document.get_entity(dimension).is_some_and(|entity| { if !matches!( - entity, - EntityType::Dimension( - Dimension::Radius(_) | Dimension::Diameter(_) | Dimension::LargeRadial(_) - ) + crate::entities::dimension::as_dimension(entity), + Some(Dimension::Radius(_) | Dimension::Diameter(_) | Dimension::LargeRadial(_)) ) { return true; } @@ -1652,7 +1650,7 @@ impl Scene { let Some(EntityType::Dimension(entity)) = self.document.get_entity(dimension) else { return Vec::new(); }; - let radial_data = match entity { + let radial_data = match &**entity { Dimension::Radius(radius) => Some(( radius.angle_vertex, radius.measurement(), @@ -1850,8 +1848,8 @@ impl Scene { continue; }; let angular = matches!( - &before, - EntityType::Dimension(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) + crate::entities::dimension::as_dimension(&before), + Some(Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_)) ); let measurement_scale = if let Some(frame) = map.frame.filter(|_| !angular) { let Some(mut scale) = persisted_measurement_scale(&self.document, &before) else { @@ -1874,7 +1872,7 @@ impl Scene { else { continue; }; - match dimension { + match &mut **dimension { Dimension::Linear(linear) => { // The sheet annotation the user placed — the dimension // line's standoff and, when they dragged it, the text — is @@ -2104,7 +2102,7 @@ impl Scene { arc.base.actual_measurement = arc.measurement(); } } - let measurement = match &*dimension { + let measurement = match &**dimension { Dimension::Linear(linear) => linear_measurement(linear), _ => dimension.measurement(), }; @@ -2155,8 +2153,12 @@ impl Scene { refreshed } pub(crate) fn sync_diameter_association_angle(&mut self, dimension: Handle) { - let chord = match self.document.get_entity(dimension) { - Some(EntityType::Dimension(Dimension::Diameter(diameter))) => diameter.angle_vertex, + let chord = match self + .document + .get_entity(dimension) + .and_then(crate::entities::dimension::as_dimension) + { + Some(Dimension::Diameter(diameter)) => diameter.angle_vertex, _ => return, }; @@ -2247,9 +2249,9 @@ mod tests { Vector3::ZERO, 5.0, ))); - let dimension = scene.add_entity(EntityType::Dimension(Dimension::Diameter( + let dimension = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Diameter( DimensionDiameter::new(Vector3::new(5.0, 0.0, 0.0), Vector3::new(-5.0, 0.0, 0.0)), - ))); + )))); scene.attach_dimension_association(dimension, vec![Some(circle)]); let association = scene .document @@ -2270,8 +2272,10 @@ mod tests { .expect("diameter association"); scene.begin_undo_recording(); - let Some(EntityType::Dimension(Dimension::Diameter(diameter))) = - scene.document.get_entity_mut(dimension) + let Some(Dimension::Diameter(diameter)) = scene + .document + .get_entity_mut(dimension) + .and_then(crate::entities::dimension::as_dimension_mut) else { panic!("diameter dimension"); }; diff --git a/src/scene/entity.rs b/src/scene/entity.rs index 2b6c14419..ac89c65c6 100644 --- a/src/scene/entity.rs +++ b/src/scene/entity.rs @@ -3206,7 +3206,7 @@ impl Scene { if let Some(origin) = model.pattern_origin { dxf.record_pattern_origin(Vector2::new(origin[0], origin[1])); } - let mut entity = EntityType::Hatch(dxf); + let mut entity = EntityType::Hatch(Box::new(dxf)); if let Some(layer) = layer { entity.as_entity_mut().set_layer(layer.to_string()); diff --git a/src/scene/layout.rs b/src/scene/layout.rs index a727d8fe7..d10d5d461 100644 --- a/src/scene/layout.rs +++ b/src/scene/layout.rs @@ -64,10 +64,10 @@ impl Scene { if let Some(EntityType::Viewport(sheet)) = self.document.get_entity(from.viewport).cloned() { if let Some(EntityType::Viewport(target)) = self.document.get_entity_mut(to.viewport) { - *target = codec::entities::Viewport { + *target = Box::new(codec::entities::Viewport { common: target.common.clone(), - ..sheet - }; + ..*sheet + }); } } self.unopened_layouts.remove(name); diff --git a/src/scene/mod.rs b/src/scene/mod.rs index d90117db5..b79bf2ae8 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -1221,12 +1221,6 @@ pub struct DerivedCaches { /// Prepared during file open so entity selection/deselection never scans /// the complete object store on the UI thread. pub object_data: crate::entities::object_data::ObjectDataCache, - /// Number of entities removed by the corrupt-entity guard during load. - /// Reported back to the UI so the user knows when a file had parser-junk - /// entities silently dropped. - pub corrupt_dropped: usize, - /// Corrupt entities dropped while resolving referenced drawings. - pub xref_dropped: usize, /// XREF resolution results produced by the loader worker. Keeping these in /// the open bundle prevents parsing and merging references on the UI thread. pub xrefs: Vec, @@ -1523,8 +1517,6 @@ fn build_derived_caches_impl( meshes, block_meshes, object_data, - corrupt_dropped: 0, - xref_dropped: 0, xrefs: Vec::new(), prepared_geometry: None, timings: OpenTimings::default(), @@ -4956,7 +4948,7 @@ impl Scene { fit_sheet_viewport(&mut vp, min_lim, max_lim); if let Ok(handle) = self .document - .add_entity_to_layout(EntityType::Viewport(vp), layout_name) + .add_entity_to_layout(EntityType::Viewport(Box::new(vp)), layout_name) { if let Some(ObjectType::Layout(l)) = self.document.objects.get_mut(&layout_handle) { l.viewports.retain(|candidate| *candidate != handle); @@ -5027,7 +5019,7 @@ impl Scene { viewport.status = codec::entities::ViewportStatusFlags::default_on(); if let Ok(handle) = self .document - .add_entity_to_layout(EntityType::Viewport(viewport), layout_name) + .add_entity_to_layout(EntityType::Viewport(Box::new(viewport)), layout_name) { // The reference zooms the new viewport to the model's extents // with a margin of under one percent. @@ -13802,7 +13794,7 @@ mod journal_tests { let mut annotative = MText::new(); annotative.value = "annotative".to_string(); annotative.is_annotative = true; - let annotative = s.add_entity(EntityType::MText(annotative)); + let annotative = s.add_entity(EntityType::MText(Box::new(annotative))); let before_points = s.geometry_epoch; s.invalidate_point_dependencies(); @@ -14117,7 +14109,7 @@ mod journal_tests { scene.document.layers.add_or_replace(Layer::new("Shadows")); let mut hatch = Hatch::new(); hatch.common.layer = "Shadows".to_string(); - let handle = scene.add_entity(EntityType::Hatch(hatch)); + let handle = scene.add_entity(EntityType::Hatch(Box::new(hatch))); let model = scene.model_space_block_handle(); assert_eq!( scene @@ -15447,7 +15439,7 @@ mod layout_cache_tests { vp.height = 100.0; let handle = scene .document - .add_entity_to_layout(codec::EntityType::Viewport(vp), "P1") + .add_entity_to_layout(codec::EntityType::Viewport(Box::new(vp)), "P1") .unwrap(); assert!(scene.set_viewport_scale_named_for(handle, "1:50").is_some()); assert!(scene.active_viewport.is_none()); diff --git a/src/scene/mspace.rs b/src/scene/mspace.rs index 688376cca..d1c01595d 100644 --- a/src/scene/mspace.rs +++ b/src/scene/mspace.rs @@ -285,7 +285,7 @@ mod viewport_zoom_tests { viewport.width = 100.0; viewport.height = 100.0; viewport.view_height = 200.0; - let handle = scene.add_entity(EntityType::Viewport(viewport)); + let handle = scene.add_entity(EntityType::Viewport(Box::new(viewport))); scene.active_viewport = Some(handle); let view_height = |scene: &Scene| match scene.document.get_entity(handle) { @@ -337,7 +337,7 @@ mod clip_tests { viewport.height = 20.0; viewport.clip_boundary_handle = clip; viewport.status.non_rectangular_clipping = true; - let viewport = scene.add_entity(EntityType::Viewport(viewport)); + let viewport = scene.add_entity(EntityType::Viewport(Box::new(viewport))); for (x, y, inside) in [ (2.0, 2.0, true), (8.0, 2.0, true), diff --git a/src/scene/parametric_constraints.rs b/src/scene/parametric_constraints.rs index 4accc1dfe..5ac4bc6f4 100644 --- a/src/scene/parametric_constraints.rs +++ b/src/scene/parametric_constraints.rs @@ -696,7 +696,7 @@ fn dynamic_dimension_follow_points( target.attachment_point = base.attachment_point; target.line_spacing_style = base.line_spacing_style; target.line_spacing_factor = base.line_spacing_factor; - *dimension = rebuilt; + *dimension = *rebuilt; true } @@ -794,7 +794,7 @@ fn dynamic_dimension_follow_radial( let Some(codec::EntityType::Dimension(mut rebuilt)) = rebuilt else { return false; }; - let unchanged = match (&*dimension, &rebuilt) { + let unchanged = match (&*dimension, &*rebuilt) { (Dimension::Radius(old), Dimension::Radius(new)) => { same(old.angle_vertex, new.angle_vertex) && same(old.definition_point, new.definition_point) @@ -808,7 +808,7 @@ fn dynamic_dimension_follow_radial( if unchanged { return false; } - match &mut rebuilt { + match &mut *rebuilt { Dimension::Radius(new) => new.leader_length = leader, Dimension::Diameter(new) => new.leader_length = leader, _ => {} @@ -821,7 +821,7 @@ fn dynamic_dimension_follow_radial( target.attachment_point = base.attachment_point; target.line_spacing_style = base.line_spacing_style; target.line_spacing_factor = base.line_spacing_factor; - *dimension = rebuilt; + *dimension = *rebuilt; true } @@ -881,7 +881,7 @@ fn dynamic_dimension_follow_angle( target.attachment_point = base.attachment_point; target.line_spacing_style = base.line_spacing_style; target.line_spacing_factor = base.line_spacing_factor; - *dimension = rebuilt; + *dimension = *rebuilt; true } @@ -2264,10 +2264,14 @@ impl super::Scene { }); let measured = points.filter(|_| !angular).map(|(first, second)| { let delta = second - first; - let axis = match self.document.get_entity(*dimension) { - Some(codec::EntityType::Dimension(codec::entities::Dimension::Linear( - linear, - ))) => Some((linear.rotation.cos(), linear.rotation.sin())), + let axis = match self + .document + .get_entity(*dimension) + .and_then(crate::entities::dimension::as_dimension) + { + Some(codec::entities::Dimension::Linear(linear)) => { + Some((linear.rotation.cos(), linear.rotation.sin())) + } _ => None, }; match (constraint.kind, axis) { @@ -2605,7 +2609,7 @@ impl super::Scene { // line, which breaks around the text, so the text is centred on // it rather than lifted above it. let radial = matches!( - dimension, + &**dimension, codec::entities::Dimension::Radius(_) | codec::entities::Dimension::Diameter(_) ); let centred = !radial || ov::int(xdata, ov::DIMTAD) == Some(0); @@ -2615,7 +2619,7 @@ impl super::Scene { // The reference draws dynamic distance text horizontally; an // angle's text keeps its style's alignment. let angular = matches!( - dimension, + &**dimension, codec::entities::Dimension::Angular2Ln(_) | codec::entities::Dimension::Angular3Pt(_) ); diff --git a/src/scene/project.rs b/src/scene/project.rs index a2433eadf..711d371a6 100644 --- a/src/scene/project.rs +++ b/src/scene/project.rs @@ -16,7 +16,7 @@ impl Scene { let viewports: Vec<&Viewport> = viewport_handles .iter() .filter_map(|handle| match self.document.get_entity(*handle) { - Some(EntityType::Viewport(vp)) => Some(vp), + Some(EntityType::Viewport(vp)) => Some(&**vp), _ => None, }) .filter(|vp| { @@ -446,7 +446,7 @@ impl Scene { Some(EntityType::Viewport(viewport)) if viewport.common.owner_handle == paper_block && viewport.is_on() => { - Some(viewport) + Some(&**viewport) } _ => None, }) diff --git a/src/ui/node_graph.rs b/src/ui/node_graph.rs index c7ff9ded5..cdcbbc439 100644 --- a/src/ui/node_graph.rs +++ b/src/ui/node_graph.rs @@ -152,7 +152,7 @@ impl ObjectKind { EntityType::Text(e::Text::with_value("Text", origin).with_height(2.5)) } ObjectKind::MText => { - EntityType::MText(e::MText::with_value("MText", origin).with_height(2.5)) + EntityType::MText(Box::new(e::MText::with_value("MText", origin).with_height(2.5))) } } } diff --git a/src/ui/window/recovery.rs b/src/ui/window/recovery.rs index 1030a2b26..beae8d90c 100644 --- a/src/ui/window/recovery.rs +++ b/src/ui/window/recovery.rs @@ -62,10 +62,6 @@ pub fn view_window<'a>( crate::tr!("recovery", "issues-found"), report.issues_found().to_string(), ), - metric( - crate::tr!("recovery", "entities-removed"), - report.removed_total().to_string(), - ), metric( crate::tr!("recovery", "references-checked"), report.references_checked.to_string(), @@ -75,16 +71,6 @@ pub fn view_window<'a>( .width(Fill); let mut details = column![].spacing(6); - if report.referenced_entities_removed > 0 { - details = details.push( - text(format!( - "{}: {}", - crate::tr!("recovery", "referenced-entities-removed"), - report.referenced_entities_removed - )) - .size(11), - ); - } if report.references_missing > 0 || report.references_failed > 0 { details = details.push( text(format!( diff --git a/tests/active_space_roundtrip.rs b/tests/active_space_roundtrip.rs index 85739c387..15530c41a 100644 --- a/tests/active_space_roundtrip.rs +++ b/tests/active_space_roundtrip.rs @@ -90,13 +90,13 @@ fn entered_viewport_survives_a_save_and_reload() { sheet.id = 1; sheet.width = 420.0; sheet.height = 297.0; - let sheet = scene.add_entity(EntityType::Viewport(sheet)); + let sheet = scene.add_entity(EntityType::Viewport(Box::new(sheet))); let mut model = Viewport::new(); model.id = 2; model.width = 100.0; model.height = 80.0; model.view_height = 80.0; - let model = scene.add_entity(EntityType::Viewport(model)); + let model = scene.add_entity(EntityType::Viewport(Box::new(model))); assert_ne!(sheet, model); for entered in [Some(model), None] { diff --git a/tests/annotative_context_synthesis.rs b/tests/annotative_context_synthesis.rs index 1f52ce560..4de593b2e 100644 --- a/tests/annotative_context_synthesis.rs +++ b/tests/annotative_context_synthesis.rs @@ -20,7 +20,7 @@ fn empty_annotation_scales_is_not_annotative() { let mut doc = CadDocument::with_version(DxfVersion::AC1032); let mut m = MText::new(); m.is_annotative = false; // no native flag, no annotative style - let ent = doc.add_entity(EntityType::MText(m)).unwrap(); + let ent = doc.add_entity(EntityType::MText(Box::new(m))).unwrap(); // Build xdict -> "AcDbContextDataManager" -> "ACDB_ANNOTATIONSCALES" (empty). let mk = |doc: &mut CadDocument, owner: Handle| -> Handle { @@ -92,7 +92,7 @@ fn ocs_synthesized_mtext_context_survives_dwg_roundtrip() { m.insertion_point = Vector3::new(100.0, 200.0, 0.0); m.rectangle_width = 50.0; m.is_annotative = true; - let ent = doc.add_entity(EntityType::MText(m)).expect("add mtext"); + let ent = doc.add_entity(EntityType::MText(Box::new(m))).expect("add mtext"); let sh = doc.allocate_handle(); let mut scale = Scale::new("1:50", 1.0, 50.0); @@ -174,7 +174,7 @@ fn object_scale_membership_add_remove_roundtrips() { let mut doc = CadDocument::with_version(DxfVersion::AC1032); let mut m = MText::new(); m.insertion_point = Vector3::new(1.0, 2.0, 0.0); - let ent = doc.add_entity(EntityType::MText(m)).unwrap(); + let ent = doc.add_entity(EntityType::MText(Box::new(m))).unwrap(); let mk_scale = |doc: &mut CadDocument, name: &str, d: f64| { let h = doc.allocate_handle(); diff --git a/tests/block_hatch_export.rs b/tests/block_hatch_export.rs index b65381871..574d2c98f 100644 --- a/tests/block_hatch_export.rs +++ b/tests/block_hatch_export.rs @@ -75,7 +75,7 @@ fn block_internal_hatch_reaches_export() { // A blue hatch, wrapped into a block and inserted in model space — the // minimal shape of "coloured fill nested in a block". - let h = scene.add_entity(EntityType::Hatch(square_hatch(5))); + let h = scene.add_entity(EntityType::Hatch(Box::new(square_hatch(5)))); let identity = codec::types::Transform::identity(); scene .create_block_from_entities(&[h], "LOGO", &identity, &identity) @@ -100,7 +100,7 @@ fn block_internal_hatch_reaches_export() { fn pattern_hatch_uses_stored_line_spacing() { let mut scene = Scene::new(); // Spacing 0.5; a big pattern_scale (10) that the catalog path would apply. - scene.add_entity(EntityType::Hatch(ansi31_stored(0.5, 10.0))); + scene.add_entity(EntityType::Hatch(Box::new(ansi31_stored(0.5, 10.0)))); scene.populate_hatches_from_document(); let hatches = scene.paper_plot_hatches(); @@ -143,7 +143,7 @@ fn far_from_origin_pattern_hatch_still_fills() { // the perpendicular index is |k| ≈ 4000·sin45°/0.3 ≈ 9400, well past the // 4096 clamp on both ends; the old absolute-index clamp inverts the range // (k_lo > k_hi) there and emits nothing. - scene.add_entity(EntityType::Hatch(ansi31_stored_at(0.3, 1.0, 4000.0, 0.0))); + scene.add_entity(EntityType::Hatch(Box::new(ansi31_stored_at(0.3, 1.0, 4000.0, 0.0)))); scene.populate_hatches_from_document(); let hatches = scene.paper_plot_hatches(); @@ -188,7 +188,7 @@ fn textbox_boundary_path_is_not_filled() { let mut tb = rect_path(0.0, 0.0, 200.0, 50.0); tb.flags = BoundaryPathFlags::from_bits(8 | 1); // TEXTBOX + EXTERNAL hatch.paths.push(tb); - scene.add_entity(EntityType::Hatch(hatch)); + scene.add_entity(EntityType::Hatch(Box::new(hatch))); scene.populate_hatches_from_document(); let hatches = scene.paper_plot_hatches(); diff --git a/tests/dim_copy_check.rs b/tests/dim_copy_check.rs index 0eb46f9cb..03388833c 100644 --- a/tests/dim_copy_check.rs +++ b/tests/dim_copy_check.rs @@ -28,7 +28,7 @@ fn copy_dimension_duplicates_its_block() { // A linear dimension whose drawn geometry is that baked block. let mut dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); dim.base.block_name = "*D0".to_string(); - let dim_h = scene.add_entity(EntityType::Dimension(Dimension::Linear(dim))); + let dim_h = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))); // Copy the dimension by (0, 50). let copies = scene.copy_entities( diff --git a/tests/dim_leader_render_check.rs b/tests/dim_leader_render_check.rs index 2484b52ef..7c48bf7d4 100644 --- a/tests/dim_leader_render_check.rs +++ b/tests/dim_leader_render_check.rs @@ -38,7 +38,7 @@ fn dim_leader_extends_only_when_requested() { base.insertion_point = base.text_middle_point; base.text_user_positioned = true; base.style_name = "Standard".into(); - let handle = scene.add_entity(EntityType::Dimension(dim)); + let handle = scene.add_entity(EntityType::Dimension(Box::new(dim))); for (code, value) in [ (ov::DIMTMOVE, XDataValue::Integer16(movement)), (ov::DIMTXT, XDataValue::Real(3.5)), diff --git a/tests/dim_line_color_roundtrip.rs b/tests/dim_line_color_roundtrip.rs index 1f800be11..e67d9a687 100644 --- a/tests/dim_line_color_roundtrip.rs +++ b/tests/dim_line_color_roundtrip.rs @@ -70,7 +70,7 @@ fn dimension_scene(aci: i16) -> Scene { let mut dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); dim.base.block_name = "*D0".to_string(); - let h = scene.add_entity(EntityType::Dimension(Dimension::Linear(dim))); + let h = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))); dov::set( &mut scene.document, h, diff --git a/tests/explode_regression.rs b/tests/explode_regression.rs index 1b277e15d..9ec6bbc95 100644 --- a/tests/explode_regression.rs +++ b/tests/explode_regression.rs @@ -130,7 +130,7 @@ fn explode_dimension_linear_golden_segments() { let mut d = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(10.0, 0.0, 0.0)); d.definition_point = Vector3::new(5.0, 3.0, 0.0); d.base.text_middle_point = Vector3::new(5.0, 5.0, 0.0); - let pieces = explode_entity(&EntityType::Dimension(Dimension::Linear(d)), &doc); + let pieces = explode_entity(&EntityType::Dimension(Box::new(Dimension::Linear(d))), &doc); // A baked linear dimension explodes to exactly 2 extension lines + 1 // dimension line. The arrowheads bake as SOLIDs (see the unit test // `linear_dim_bakes_filled_arrowheads`), which is why the Lines count is diff --git a/tests/pdf_export_images_check.rs b/tests/pdf_export_images_check.rs index 6859e6a1c..5e552458c 100644 --- a/tests/pdf_export_images_check.rs +++ b/tests/pdf_export_images_check.rs @@ -331,7 +331,7 @@ fn viewport_projection_clips_images_and_respects_frozen_and_nonplot_layers() { viewport.view_center = Vector3::new(20.0, 10.0, 0.0); viewport.id = 2; viewport.status.is_on = true; - let handle = scene.add_entity(EntityType::Viewport(viewport)); + let handle = scene.add_entity(EntityType::Viewport(Box::new(viewport))); let (_, _, _, images) = scene.viewport_plot_fills(); assert_eq!(images.len(), 1); let raster = Raster::from_pdf(&export(&[page(images)]), 0); diff --git a/tests/pdf_export_text_check.rs b/tests/pdf_export_text_check.rs index 8ad8037b3..947f6092e 100644 --- a/tests/pdf_export_text_check.rs +++ b/tests/pdf_export_text_check.rs @@ -26,7 +26,7 @@ fn text_and_dim_reach_pdf_export() { // A linear dimension — its measurement value is synthesized as SDF text too, // and dimension text is what #385 was actually filed about. let dim = DimensionLinear::new(Vector3::new(0.0, 0.0, 0.0), Vector3::new(40.0, 0.0, 0.0)); - let dim_h = scene.add_entity(EntityType::Dimension(Dimension::Linear(dim))); + let dim_h = scene.add_entity(EntityType::Dimension(Box::new(Dimension::Linear(dim)))); let wires = scene.entity_wires(); diff --git a/tests/text_font_rendering.rs b/tests/text_font_rendering.rs index 805988e6a..66ba96bf0 100644 --- a/tests/text_font_rendering.rs +++ b/tests/text_font_rendering.rs @@ -43,7 +43,7 @@ fn expand_block_mtext( mtext.style = "SHOP".to_string(); mtext.height = 20.0; mtext.rectangle_width = 0.0; - let mut sub = EntityType::MText(mtext); + let mut sub = EntityType::MText(Box::new(mtext)); sub.common_mut().owner_handle = br_h; doc.add_entity(sub).unwrap(); diff --git a/tests/viewport_wide_polyline_plot_width.rs b/tests/viewport_wide_polyline_plot_width.rs index 8ccf6851c..d898b5b43 100644 --- a/tests/viewport_wide_polyline_plot_width.rs +++ b/tests/viewport_wide_polyline_plot_width.rs @@ -43,7 +43,7 @@ fn viewport_projection_scales_wide_polyline_band_width() { viewport.view_center = Vector3::new(50.0, 0.0, 0.0); viewport.id = 2; viewport.status.is_on = true; - scene.add_entity(EntityType::Viewport(viewport)); + scene.add_entity(EntityType::Viewport(Box::new(viewport))); let (_paper, model) = scene.plot_wire_groups(None); let band = model diff --git a/tests/zoom_extents_coverage.rs b/tests/zoom_extents_coverage.rs index 455349760..c8fbb518d 100644 --- a/tests/zoom_extents_coverage.rs +++ b/tests/zoom_extents_coverage.rs @@ -75,7 +75,7 @@ fn fit_all_reaches_an_entity_parked_far_from_the_rest() { #[test] fn fit_all_frames_a_hatch_only_drawing() { let mut scene = Scene::new(); - scene.add_entity(EntityType::Hatch(square_hatch(100.0, 200.0, 40.0))); + scene.add_entity(EntityType::Hatch(Box::new(square_hatch(100.0, 200.0, 40.0)))); scene.fit_all(); @@ -103,7 +103,7 @@ fn fit_all_keeps_a_hatch_outside_the_wires_in_view() { } // The fill is the outermost thing in the drawing; the wires alone would // frame a 12 x 10 strip and leave it off screen. - scene.add_entity(EntityType::Hatch(square_hatch(500.0, 500.0, 50.0))); + scene.add_entity(EntityType::Hatch(Box::new(square_hatch(500.0, 500.0, 50.0)))); scene.fit_all();