fix(text): integrate ignored fields across text-bearing entities
- MultiLeader: stop double-scaling when ctx.text_height (WCS-baked) is set;
use it as-is and only multiply by scale_factor + anno on the fallback path.
ctx.text_width gets the same treatment.
- Text / Attribute: width_factor and oblique_angle are entity-authoritative.
The previous entity*style multiplication / addition mis-rendered any text
whose TXSTYLE had a non-default width_factor or oblique_angle (RR 0.6,
STYLE2 15°, Romans/ARIEL/A32 0.65-0.8 in the sample file).
- MText: honour TXSTYLE is_backward (negative width_factor mirror) and
is_upside_down (180° rotation). measure_mtext_chars uses positive
magnitude so anchor math stays correct under backward text.
- Tolerance: use tol.dimension_gap when set instead of the hard-coded
0.35 * height heuristic.
- Table: cell text height / font / alignment resolve through
CellContent -> CellStyle -> TableStyle.{title|header|data}_row_style
-> compiled-in defaults. Row classification respects the suppressed
flags. Cell + content rotation applied.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
ace99541d0
commit
62876b1081
7 changed files with 198 additions and 55 deletions
|
|
@ -1552,12 +1552,18 @@ pub fn tessellate_multileader(
|
|||
// text_left_attachment (vertical), with text_rotation/text_direction applied.
|
||||
if ml.content_type == LeaderContentType::MText && !ml.context.text_string.is_empty() {
|
||||
let ctx = &ml.context;
|
||||
let raw_height = if ctx.text_height > 0.0 {
|
||||
ctx.text_height
|
||||
// `ctx.text_height` (when > 0) is the already-resolved WCS text height
|
||||
// stored in the per-instance context — style × scale_factor × anno
|
||||
// scale are all already baked in. Multiplying by `effective_scale`
|
||||
// again would double-scale (e.g., a context height of 100 in a file
|
||||
// with scale_factor=20 was rendering at 2000 units — 20× too big).
|
||||
// Only the fallback path (file omits the context value) needs
|
||||
// scale_factor + annotation scale applied.
|
||||
let height = if ctx.text_height > 0.0 {
|
||||
ctx.text_height as f32
|
||||
} else {
|
||||
ml.text_height
|
||||
} as f32;
|
||||
let height = raw_height * effective_scale;
|
||||
ml.text_height as f32 * effective_scale
|
||||
};
|
||||
|
||||
let ins = &ctx.text_location;
|
||||
// Subtract world_offset in f64 before casting to f32: drawings often
|
||||
|
|
@ -1595,7 +1601,6 @@ pub fn tessellate_multileader(
|
|||
if ml.text_direction_negative {
|
||||
rot += std::f32::consts::PI;
|
||||
}
|
||||
let (cos_r, sin_r) = (rot.cos(), rot.sin());
|
||||
|
||||
// Resolve text style via handle when available, falling back to STANDARD.
|
||||
let style_name = ctx
|
||||
|
|
@ -1612,16 +1617,29 @@ pub fn tessellate_multileader(
|
|||
let style = crate::entities::text_support::resolve_text_style(&style_name, document);
|
||||
let font_name = style.font_name;
|
||||
let font = crate::scene::cxf::get_font(&font_name);
|
||||
let width_factor = style.width_factor.max(0.01);
|
||||
// MultiLeader text takes its width factor / oblique from the style
|
||||
// (no entity-level override exists for MText-content multileaders).
|
||||
// is_backward flips the sign on width_factor; is_upside_down adds π
|
||||
// to the text rotation — same convention as Text / MText.
|
||||
let base_wf = style.width_factor.max(0.01);
|
||||
let width_factor = if style.is_backward { -base_wf } else { base_wf };
|
||||
let oblique = style.oblique_angle;
|
||||
if style.is_upside_down {
|
||||
rot += std::f32::consts::PI;
|
||||
}
|
||||
let (cos_r, sin_r) = (rot.cos(), rot.sin());
|
||||
|
||||
// Strip MText format codes (e.g. `{\fArial Black|b0|i0|c162|p34;...}`),
|
||||
// then split on \P / \n / \N and optionally word-wrap to text_width.
|
||||
let plain = crate::entities::text_support::strip_mtext_codes(&ctx.text_string);
|
||||
let explicit_lines = crate::entities::text_support::split_mtext_lines(&plain);
|
||||
let lines: Vec<String> = if ctx.text_width > 0.0 {
|
||||
let scale = height / 9.0 * width_factor;
|
||||
let max_w = ctx.text_width as f32 * effective_scale;
|
||||
// Measurement uses positive width magnitude; the sign on
|
||||
// width_factor is a render-time mirror flag.
|
||||
let scale = height / 9.0 * width_factor.abs();
|
||||
// ctx.text_width lives in the same WCS frame as ctx.text_height;
|
||||
// it does not need a second multiplication by effective_scale.
|
||||
let max_w = ctx.text_width as f32;
|
||||
explicit_lines
|
||||
.iter()
|
||||
.flat_map(|line| {
|
||||
|
|
@ -1676,7 +1694,9 @@ pub fn tessellate_multileader(
|
|||
};
|
||||
let v_offset = v_offset_for_attachment(vertical_attach, n_lines, height, line_h);
|
||||
|
||||
let scale = height / 9.0 * width_factor;
|
||||
// line_widths use positive magnitude for measurement; tessellate_text_ex
|
||||
// gets the signed width_factor below to honour the backward flag.
|
||||
let scale = height / 9.0 * width_factor.abs();
|
||||
let line_widths: Vec<f32> = lines
|
||||
.iter()
|
||||
.map(|line| crate::entities::text_support::measure_mtext_chars(line, scale, font))
|
||||
|
|
|
|||
Loading…
Reference in a new issue