fix(web): preserve DWG render state
Carry rendering fields omitted by document serialization and normalize block origins before building web caches.
This commit is contained in:
parent
a1f64d7663
commit
6cafea92bc
6 changed files with 104 additions and 6 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -3769,6 +3769,7 @@ dependencies = [
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
"serde",
|
||||||
"sha2 0.10.9",
|
"sha2 0.10.9",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ crate-type = ["cdylib"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "7e2fa8c", features = ["serde"] }
|
acadrust = { git = "https://github.com/HakanSeven12/cadcodec.git", rev = "7e2fa8c", features = ["serde"] }
|
||||||
bincode = "1.3"
|
bincode = "1.3"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
getrandom = { version = "0.3", features = ["wasm_js"] }
|
getrandom = { version = "0.3", features = ["wasm_js"] }
|
||||||
js-sys = "0.3"
|
js-sys = "0.3"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,23 @@ use sha2::{Digest, Sha256};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
const HASH_MARKER: &str = "\nreport-source-sha256:";
|
const HASH_MARKER: &str = "\nreport-source-sha256:";
|
||||||
const PROTOCOL_VERSION: u16 = 3;
|
const PROTOCOL_VERSION: u16 = 4;
|
||||||
|
|
||||||
|
#[derive(serde::Serialize)]
|
||||||
|
struct EntityRuntimeFields {
|
||||||
|
handle: u64,
|
||||||
|
linetype_handle: Option<u64>,
|
||||||
|
color_book_handle: Option<u64>,
|
||||||
|
face_visual_style_handle: Option<u64>,
|
||||||
|
edge_visual_style_handle: Option<u64>,
|
||||||
|
material_flags: u8,
|
||||||
|
material_handle: Option<u64>,
|
||||||
|
shadow_flags: u8,
|
||||||
|
plotstyle_flags: u8,
|
||||||
|
plotstyle_handle: Option<u64>,
|
||||||
|
entity_mode: Option<u8>,
|
||||||
|
has_ds_data: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse DWG/DXF on a dedicated browser worker and return a compact serialized
|
/// Parse DWG/DXF on a dedicated browser worker and return a compact serialized
|
||||||
/// document. The main wasm instance only deserializes and installs it, so the
|
/// document. The main wasm instance only deserializes and installs it, so the
|
||||||
|
|
@ -159,11 +175,43 @@ fn encode_result(
|
||||||
recoverable_parse_error: bool,
|
recoverable_parse_error: bool,
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
) -> Result<Uint8Array, JsValue> {
|
) -> Result<Uint8Array, JsValue> {
|
||||||
|
let runtime_fields = result
|
||||||
|
.as_ref()
|
||||||
|
.ok()
|
||||||
|
.map(|outcome| {
|
||||||
|
outcome
|
||||||
|
.document
|
||||||
|
.entities()
|
||||||
|
.map(|entity| {
|
||||||
|
let common = entity.common();
|
||||||
|
EntityRuntimeFields {
|
||||||
|
handle: common.handle.value(),
|
||||||
|
linetype_handle: common.linetype_handle.map(|handle| handle.value()),
|
||||||
|
color_book_handle: common.color_book_handle.map(|handle| handle.value()),
|
||||||
|
face_visual_style_handle: common
|
||||||
|
.face_visual_style_handle
|
||||||
|
.map(|handle| handle.value()),
|
||||||
|
edge_visual_style_handle: common
|
||||||
|
.edge_visual_style_handle
|
||||||
|
.map(|handle| handle.value()),
|
||||||
|
material_flags: common.material_flags,
|
||||||
|
material_handle: common.material_handle.map(|handle| handle.value()),
|
||||||
|
shadow_flags: common.shadow_flags,
|
||||||
|
plotstyle_flags: common.plotstyle_flags,
|
||||||
|
plotstyle_handle: common.plotstyle_handle.map(|handle| handle.value()),
|
||||||
|
entity_mode: common.entity_mode,
|
||||||
|
has_ds_data: common.has_ds_data,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
let encoded = bincode::serialize(&(
|
let encoded = bincode::serialize(&(
|
||||||
PROTOCOL_VERSION,
|
PROTOCOL_VERSION,
|
||||||
result,
|
result,
|
||||||
source_sha256,
|
source_sha256,
|
||||||
recoverable_parse_error,
|
recoverable_parse_error,
|
||||||
|
runtime_fields,
|
||||||
))
|
))
|
||||||
.map_err(|error| worker_error(error.to_string(), bytes, true))?;
|
.map_err(|error| worker_error(error.to_string(), bytes, true))?;
|
||||||
Ok(Uint8Array::from(encoded.as_slice()))
|
Ok(Uint8Array::from(encoded.as_slice()))
|
||||||
|
|
|
||||||
|
|
@ -663,6 +663,7 @@ async fn load_web_bytes(
|
||||||
merge_read_diagnostics(&mut outcome.stats, initial_stats);
|
merge_read_diagnostics(&mut outcome.stats, initial_stats);
|
||||||
}
|
}
|
||||||
let mut doc = outcome.document;
|
let mut doc = outcome.document;
|
||||||
|
normalize_block_origins(&mut doc);
|
||||||
if name.to_ascii_lowercase().ends_with(".dxf") {
|
if name.to_ascii_lowercase().ends_with(".dxf") {
|
||||||
fix_dxf_dimension_rotations(&mut doc);
|
fix_dxf_dimension_rotations(&mut doc);
|
||||||
fix_dxf_layout_plot_settings(&mut doc);
|
fix_dxf_layout_plot_settings(&mut doc);
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,24 @@ use wasm_bindgen::{JsCast, JsValue};
|
||||||
use web_sys::{ErrorEvent, MessageEvent, Worker, WorkerOptions, WorkerType};
|
use web_sys::{ErrorEvent, MessageEvent, Worker, WorkerOptions, WorkerType};
|
||||||
|
|
||||||
const HASH_MARKER: &str = "\nreport-source-sha256:";
|
const HASH_MARKER: &str = "\nreport-source-sha256:";
|
||||||
const PROTOCOL_VERSION: u16 = 3;
|
const PROTOCOL_VERSION: u16 = 4;
|
||||||
const WORKER_URL: &str = "ocs-parse-worker.js?v=3";
|
const WORKER_URL: &str = "ocs-parse-worker.js?v=4";
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
struct EntityRuntimeFields {
|
||||||
|
handle: u64,
|
||||||
|
linetype_handle: Option<u64>,
|
||||||
|
color_book_handle: Option<u64>,
|
||||||
|
face_visual_style_handle: Option<u64>,
|
||||||
|
edge_visual_style_handle: Option<u64>,
|
||||||
|
material_flags: u8,
|
||||||
|
material_handle: Option<u64>,
|
||||||
|
shadow_flags: u8,
|
||||||
|
plotstyle_flags: u8,
|
||||||
|
plotstyle_handle: Option<u64>,
|
||||||
|
entity_mode: Option<u8>,
|
||||||
|
has_ds_data: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) async fn parse_document(
|
pub(super) async fn parse_document(
|
||||||
name: &str,
|
name: &str,
|
||||||
|
|
@ -45,6 +61,7 @@ pub(super) async fn parse_document(
|
||||||
>,
|
>,
|
||||||
Option<String>,
|
Option<String>,
|
||||||
bool,
|
bool,
|
||||||
|
Vec<EntityRuntimeFields>,
|
||||||
) = bincode::deserialize(&bytes)
|
) = bincode::deserialize(&bytes)
|
||||||
.map_err(|error| super::OpenLoadError::from(error.to_string()))?;
|
.map_err(|error| super::OpenLoadError::from(error.to_string()))?;
|
||||||
if payload.0 != PROTOCOL_VERSION {
|
if payload.0 != PROTOCOL_VERSION {
|
||||||
|
|
@ -54,7 +71,13 @@ pub(super) async fn parse_document(
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
match payload.1 {
|
match payload.1 {
|
||||||
Ok(outcome) => Ok((outcome, payload.2)),
|
Ok(mut outcome) => {
|
||||||
|
restore_entity_runtime_fields(
|
||||||
|
&mut outcome.document,
|
||||||
|
payload.4,
|
||||||
|
);
|
||||||
|
Ok((outcome, payload.2))
|
||||||
|
}
|
||||||
Err((message, read_stats)) => Err(super::OpenLoadError {
|
Err((message, read_stats)) => Err(super::OpenLoadError {
|
||||||
message,
|
message,
|
||||||
source_sha256: payload.2,
|
source_sha256: payload.2,
|
||||||
|
|
@ -119,6 +142,30 @@ pub(super) async fn parse_document(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn restore_entity_runtime_fields(
|
||||||
|
document: &mut acadrust::CadDocument,
|
||||||
|
fields: Vec<EntityRuntimeFields>,
|
||||||
|
) {
|
||||||
|
let handle = |value: Option<u64>| value.map(acadrust::Handle::new);
|
||||||
|
for fields in fields {
|
||||||
|
let Some(entity) = document.get_entity_mut(acadrust::Handle::new(fields.handle)) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let common = entity.common_mut();
|
||||||
|
common.linetype_handle = handle(fields.linetype_handle);
|
||||||
|
common.color_book_handle = handle(fields.color_book_handle);
|
||||||
|
common.face_visual_style_handle = handle(fields.face_visual_style_handle);
|
||||||
|
common.edge_visual_style_handle = handle(fields.edge_visual_style_handle);
|
||||||
|
common.material_flags = fields.material_flags;
|
||||||
|
common.material_handle = handle(fields.material_handle);
|
||||||
|
common.shadow_flags = fields.shadow_flags;
|
||||||
|
common.plotstyle_flags = fields.plotstyle_flags;
|
||||||
|
common.plotstyle_handle = handle(fields.plotstyle_handle);
|
||||||
|
common.entity_mode = fields.entity_mode;
|
||||||
|
common.has_ds_data = fields.has_ds_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) async fn sha256_document(bytes: &[u8]) -> Result<String, super::OpenLoadError> {
|
pub(super) async fn sha256_document(bytes: &[u8]) -> Result<String, super::OpenLoadError> {
|
||||||
let options = WorkerOptions::new();
|
let options = WorkerOptions::new();
|
||||||
options.set_type(WorkerType::Module);
|
options.set_type(WorkerType::Module);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import init, { parse_document, sha256_document } from "./worker_pkg/ocs_web_worker.js?v=3";
|
import init, { parse_document, sha256_document } from "./worker_pkg/ocs_web_worker.js?v=4";
|
||||||
|
|
||||||
const ready = init(
|
const ready = init(
|
||||||
new URL("./worker_pkg/ocs_web_worker_bg.wasm?v=3", import.meta.url),
|
new URL("./worker_pkg/ocs_web_worker_bg.wasm?v=4", import.meta.url),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.onmessage = async ({ data }) => {
|
self.onmessage = async ({ data }) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue