diff --git a/Cargo.lock b/Cargo.lock index 4f241e9e6..063cfe1d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4206,7 +4206,7 @@ dependencies = [ [[package]] name = "opencadcodec" version = "0.5.5" -source = "git+https://github.com/ramox81/cadcodec.git?rev=07191be#07191be6571c43d8334eb7da02e6d42283246628" +source = "git+https://github.com/ramox81/cadcodec.git?rev=24bdac7#24bdac79787a8196227c43cc840277f302e7e124" dependencies = [ "ahash 0.8.12", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 138a3301c..1ac2ede73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,7 +95,7 @@ iced_core = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aa iced_widget = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" } [patch."https://github.com/HakanSeven12/opencadcodec.git"] -opencadcodec = { git = "https://github.com/ramox81/cadcodec.git", rev = "07191be" } +opencadcodec = { git = "https://github.com/ramox81/cadcodec.git", rev = "24bdac7" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] getrandom = "0.3" diff --git a/src/entities/field.rs b/src/entities/field.rs index 29af2e20b..d8d6d5bf1 100644 --- a/src/entities/field.rs +++ b/src/entities/field.rs @@ -299,6 +299,12 @@ pub fn set_display(on: bool) { } /// The gray the reference draws behind a field. +/// FIELDDISPLAY box extent around a line of field text, in text heights: +/// from a third of the height below the baseline to 1.19 heights above it +/// (the reference's box, measured at 2.5 and 10 unit text). +pub const BOX_BELOW: f64 = 0.345; +pub const BOX_ABOVE: f64 = 1.19; + pub const BACKGROUND: [f32; 4] = [203.0 / 255.0, 203.0 / 255.0, 203.0 / 255.0, 1.0]; /// Whether `entity` hosts a field: its extension dictionary has ACAD_FIELD. diff --git a/src/entities/table.rs b/src/entities/table.rs index ebe5e3a7f..81b154042 100644 --- a/src/entities/table.rs +++ b/src/entities/table.rs @@ -1525,6 +1525,7 @@ pub fn tessellate_table( // Accumulators keyed by quantised colour (+ weight for borders). let mut fills: HashMap<[u8; 4], ([f32; 4], Vec<[f32; 3]>)> = HashMap::default(); + let mut field_fills: Vec<[f32; 3]> = Vec::new(); // SDF cell text: glyph quads (per-vertex coloured) collected across all // cells; emitted as one text-carrying wire at the end. let mut text_verts: Vec = Vec::new(); @@ -1972,6 +1973,50 @@ pub fn tessellate_table( vertical_text: false, want_glyph_boxes: false, }); + // FIELDDISPLAY: a field cell's text on a gray box, one per line, + // from the same layout's character cells (screen only). + if content.field_handle.is_some() && crate::entities::field::display() { + let cells = layout_mtext(&MTextRenderOpts { + columns: Default::default(), + value: text, + insertion: [to.x as f64, to.y as f64, to.z as f64], + height: cell_h, + rect_w: (col_width - margin_left - margin_right).max(0.0), + rotation: rot, + style: &resolved, + attach_h_anchor, + v_anchor, + line_spacing_factor: 1.0, + exact_line_spacing: false, + rectangle_height: 0.0, + vertical_text: false, + want_glyph_boxes: true, + }) + .glyph_boxes; + let (sin_r, cos_r) = (rot as f64).sin_cos(); + let mut lines: Vec<[f64; 4]> = Vec::new(); + for b in &cells { + let [l, base, r, top] = b.local.map(|v| v as f64); + match lines.last_mut() { + Some(c) if (c[1] - base).abs() <= 1e-3 * (top - base).max(c[3]) => { + c[0] = c[0].min(l); + c[2] = c[2].max(r); + c[3] = c[3].max(top - base); + } + _ => lines.push([l, base, r, top - base]), + } + } + for [l, base, r, h] in lines.into_iter().filter(|[l, _, r, _]| r > l) { + let (b, t) = (base - crate::entities::field::BOX_BELOW * h, base + crate::entities::field::BOX_ABOVE * h); + let w = |x: f64, y: f64| [ + (to.x as f64 + x * cos_r - y * sin_r) as f32, + (to.y as f64 + x * sin_r + y * cos_r) as f32, + to.z as f32, + ]; + let q = [w(l, b), w(r, b), w(r, t), w(l, t)]; + field_fills.extend([q[0], q[1], q[2], q[0], q[2], q[3]]); + } + } let tcol = if selected { sel_col } else if !matches!( @@ -2131,6 +2176,11 @@ pub fn tessellate_table( out.push(mk(color, vec![], tris, 1.0)); } } + if !field_fills.is_empty() { + let mut background = mk(crate::entities::field::BACKGROUND, vec![], field_fills, 1.0); + background.plot_visible = false; + out.push(background); + } for (_, (color, lw, pts)) in borders { if !pts.is_empty() { out.push(mk(color, pts, vec![], lw)); diff --git a/src/scene/convert/tessellate.rs b/src/scene/convert/tessellate.rs index d7afd0298..d57c5ddbb 100644 --- a/src/scene/convert/tessellate.rs +++ b/src/scene/convert/tessellate.rs @@ -78,11 +78,7 @@ fn oriented_text_corners( ] } -/// FIELDDISPLAY box extent around a line of field text, in text heights: -/// from a third of the height below the baseline to 1.19 heights above it -/// (the reference's box, measured at 2.5 and 10 unit text). -const FIELD_BOX_BELOW: f64 = 0.345; -const FIELD_BOX_ABOVE: f64 = 1.19; +use crate::entities::field::{BOX_ABOVE as FIELD_BOX_ABOVE, BOX_BELOW as FIELD_BOX_BELOW}; /// FIELDDISPLAY boxes: each field's shown text, one box per line it spans, /// placed from the text layout itself, in the text's own (rotated) frame —