ifc_lite_wasm/zero_copy/symbolic_from_data.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! The canonical → wasm conversion for symbolic primitives.
6//!
7//! Split out of `symbolic.rs` (as `symbolic_truncation.rs` was, #2938) because
8//! it is the one place in that file with a failure story of its own: everything
9//! else there is a field and its getter, while this is a hand-written
10//! transcription between two struct families that are field-for-field parallel
11//! but share no type. Nothing in the compiler can see a pair transposed or a
12//! field left behind here — only `symbolic_tests.rs` can — so the conversion and
13//! its tests belong side by side rather than buried among the accessors.
14
15use super::symbolic::{
16 SymbolicCircle, SymbolicFillArea, SymbolicPolyline, SymbolicRepresentationCollection,
17 SymbolicText,
18};
19
20impl SymbolicRepresentationCollection {
21 /// Convert from the canonical `ifc_lite_processing::SymbolicData`
22 /// (issue #843 follow-up — full parity refactor). The WASM-side
23 /// extractor now delegates to the processing crate and converts the
24 /// result here so the browser and the HTTP server produce bit-
25 /// identical symbol streams from one canonical implementation.
26 ///
27 /// "Bit-identical" is the contract, so every field of every primitive has
28 /// to cross — a field this function forgets is a field the browser silently
29 /// never sees, while the server's JSON for the same file still carries it.
30 pub fn from_data(data: ifc_lite_processing::SymbolicData) -> Self {
31 Self::from_data_and_items(data, &[])
32 }
33
34 /// Convert canonical symbols with the extraction-bound fill sidecar.
35 pub fn from_data_with_provenance(data: ifc_lite_processing::SymbolicDataWithProvenance) -> Self {
36 let (data, items) = data.into_parts();
37 Self::from_data_and_items(data, &items)
38 }
39
40 fn from_data_and_items(data: ifc_lite_processing::SymbolicData, items: &[Option<u32>]) -> Self {
41 let mut collection = Self::with_capacity(data.polylines.len(), data.circles.len());
42 collection.truncated = data.truncated.clone();
43 for p in data.polylines {
44 collection.add_polyline(SymbolicPolyline::new(
45 p.express_id,
46 p.ifc_type,
47 p.points,
48 p.closed,
49 p.world_y,
50 p.representation,
51 ));
52 }
53 for c in data.circles {
54 collection.add_circle(SymbolicCircle::new(
55 c.express_id,
56 c.ifc_type,
57 c.center_x,
58 c.center_y,
59 c.radius,
60 c.world_y,
61 c.start_angle,
62 c.end_angle,
63 c.representation,
64 ));
65 }
66 for t in data.texts {
67 collection.add_text(SymbolicText::new_styled(
68 t.express_id,
69 t.ifc_type,
70 t.x,
71 t.y,
72 t.dir_x,
73 t.dir_y,
74 t.height,
75 t.content,
76 t.alignment,
77 t.world_y,
78 t.color,
79 t.target_px,
80 t.representation,
81 ));
82 }
83 for (ordinal, f) in data.fills.into_iter().enumerate() {
84 let fill = SymbolicFillArea::new(
85 f.express_id,
86 f.ifc_type,
87 f.points,
88 f.holes_offsets,
89 f.fill_color,
90 f.world_y,
91 f.representation,
92 ).with_geometry_item_id(items.get(ordinal).copied().flatten());
93 // `SymbolicFillArea::new` defaults to unhatched, so the hatching
94 // style has to be applied explicitly. The viewer reads these five
95 // fields straight off this object
96 // (`apps/viewer/src/lib/overlay-parse/symbolic-flat.ts`), so
97 // dropping them here draws every hatched region as a flat solid in
98 // the browser while the JSON path carries the style intact.
99 //
100 // `hatch_angle_secondary` is NaN when there is no cross-hatch, and
101 // NaN is exactly what the builder's `None` restores — so route the
102 // absent case back through `Option` rather than handing the
103 // sentinel on as though it were a real angle.
104 collection.add_fill(if f.has_hatching {
105 fill.with_hatching(
106 f.hatch_spacing,
107 f.hatch_angle,
108 Some(f.hatch_angle_secondary).filter(|a| !a.is_nan()),
109 f.hatch_line_width,
110 )
111 } else {
112 fill
113 });
114 }
115 collection
116 }
117}