forked from 1b-agent/opencadstudio-upstream
fix(mtext): support arabic cursive shaping and bidirectional rtl text layout
- Enable fallback font metrics for HarfBuzz shaping in TTF glyph resolver - Implement Unicode Bidirectional Algorithm (UBA) paragraph base direction detection - Anchor right-to-left paragraphs to right container boundaries by default - Reorder line atoms with base direction level to preserve neutral punctuation attachment - Right-align RTL single-line TEXT and handle editor caret placement on RTL glyphs
This commit is contained in:
1 parent
ef189d7781
commit
f1d5284fb9
8 files changed
+577
-73
No files matched your search
+51
-2
@@ -281,10 +281,38 @@ pub fn text_run_placement_at_scale(
|
||||
// box one way while the strokes run the other (the bounds advance is
|
||||
// always positive — it uses |width_factor|). Left keeps its 0 reference.
|
||||
let sign = width_factor.signum();
|
||||
let is_rtl = {
|
||||
let mut strong_rtl = false;
|
||||
for ch in value_for_bounds.chars() {
|
||||
match unicode_bidi::bidi_class(ch) {
|
||||
unicode_bidi::BidiClass::R | unicode_bidi::BidiClass::AL => {
|
||||
strong_rtl = true;
|
||||
break;
|
||||
}
|
||||
unicode_bidi::BidiClass::L => {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
strong_rtl
|
||||
};
|
||||
let ax = match t.horizontal_alignment {
|
||||
HA::Left => 0.0,
|
||||
HA::Left => {
|
||||
if is_rtl {
|
||||
b.advance * sign
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
HA::Center | HA::Middle => b.advance * 0.5 * sign,
|
||||
HA::Right => b.advance * sign,
|
||||
HA::Right => {
|
||||
if is_rtl {
|
||||
0.0
|
||||
} else {
|
||||
b.advance * sign
|
||||
}
|
||||
}
|
||||
HA::Aligned | HA::Fit => 0.0,
|
||||
};
|
||||
// Vertical anchor uses the inked extent (cap / baseline geometry).
|
||||
@@ -684,6 +712,27 @@ impl Grippable for Text {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_arabic_text_placement() {
|
||||
let mut t = Text::default();
|
||||
t.value = "بسم الله".to_string();
|
||||
t.height = 2.5;
|
||||
t.insertion_point = acadrust::types::Vector3::new(10.0, 20.0, 0.0);
|
||||
t.horizontal_alignment = HA::Left;
|
||||
|
||||
let doc = acadrust::CadDocument::default();
|
||||
let placement = text_run_placement_at_scale(&t, &doc, 1.0);
|
||||
|
||||
// For Arabic text with default HA::Left, origin should be shifted left
|
||||
// so the right edge of the text sits at the insertion point (X = 10.0).
|
||||
assert!(placement.origin[0] < 10.0, "Arabic text origin must be to the left of insertion point: origin_x={}", placement.origin[0]);
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyEditable for Text {
|
||||
fn geometry_properties(&self, text_style_names: &[String]) -> Vec<PropSection> {
|
||||
properties(self, text_style_names)
|
||||
|
||||
Reference in new issue
Block a user