fix(scene): per-line text greek honors word-wrap subline count
`text_obb_corners_native` derived MText line count from explicit `\n`
matches in `m.value`, so any MText that relied on `\P`/`\N` breaks or
word-wrap (rectangle_width-driven) reported a single line. The greek
emitter then split the OBB into one row and the user saw a single box
on top of a 5-line wrapped paragraph.
- text_support: new `mtext_line_count` — strip codes, split on
\n/\P/\N, word-wrap each paragraph against `rectangle_width`,
sum. Same line splitting the MText/MultiLeader renderers already
perform; centralized for reuse.
- text_obb_corners_native: takes `mtext_lines_override: Option<usize>`.
When supplied, OBB height = h_world × n × line_spacing_factor; this
also overrides a possibly stale `rectangle_height` on resaved DWGs.
- Top-level greek paths (scene/mod.rs) compute the line count via
`mtext_line_count` and pass it through to baseline / rect emission.
- block_cache: tessellate_sub_local computes the count at defn build
so the stored `text_obb_local` is wrap-aware; emit_text_baseline
and emit_greeked_text recover n_lines from `ulen / h_local` as
before and now produce the correct per-row split inside Inserts.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
ddd0a2de16
commit
f4ae0e7773
3 changed files with 274 additions and 80 deletions
|
|
@ -341,6 +341,35 @@ pub fn measure_mtext_chars(text: &str, scale: f32, font: &cxf::CxfFile) -> f32 {
|
|||
width
|
||||
}
|
||||
|
||||
/// Total number of visible lines an MText renders to — explicit `\P` /
|
||||
/// `\n` / `\N` breaks plus word-wrap induced sublines when
|
||||
/// `rectangle_width > 0`. Mirrors the line-splitting `entities/mtext.rs`
|
||||
/// and `tessellate_multileader` perform; lets renderers split the OBB
|
||||
/// into per-row LOD primitives without re-running the wrap measurement.
|
||||
pub fn mtext_line_count(
|
||||
m: &acadrust::entities::MText,
|
||||
document: &CadDocument,
|
||||
anno_scale: f32,
|
||||
) -> usize {
|
||||
let resolved = resolve_text_style(&m.style, document);
|
||||
let font = cxf::get_font(&resolved.font_name);
|
||||
let width_factor = resolved.width_factor.max(0.01);
|
||||
let height = m.height as f32 * anno_scale;
|
||||
let plain = strip_mtext_codes(&m.value);
|
||||
let explicit = split_mtext_lines(&plain);
|
||||
let total: usize = if m.rectangle_width > 0.0 && height > 0.0 {
|
||||
let scale = height / 9.0 * width_factor;
|
||||
let max_w = m.rectangle_width as f32 * anno_scale;
|
||||
explicit
|
||||
.iter()
|
||||
.map(|l| word_wrap(l, max_w, scale, font).len())
|
||||
.sum()
|
||||
} else {
|
||||
explicit.len()
|
||||
};
|
||||
total.max(1)
|
||||
}
|
||||
|
||||
pub fn word_wrap(text: &str, max_w: f32, scale: f32, font: &'static cxf::CxfFile) -> Vec<String> {
|
||||
if max_w <= 0.0 || text.is_empty() {
|
||||
return vec![text.to_string()];
|
||||
|
|
|
|||
Loading…
Reference in a new issue