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
@@ -640,16 +640,16 @@ fn vertical_caret_target(
|
||||
let anchor = boxes
|
||||
.iter()
|
||||
.find(|item| item.vis == caret)
|
||||
.map(|item| (item.xmin, item.ymin, item.ymax))
|
||||
.map(|item| ((if item.is_rtl { item.xmax } else { item.xmin }), item.ymin, item.ymax))
|
||||
.or_else(|| {
|
||||
caret.checked_sub(1).and_then(|previous| {
|
||||
boxes
|
||||
.iter()
|
||||
.find(|item| item.vis == previous)
|
||||
.map(|item| (item.xmax, item.ymin, item.ymax))
|
||||
.map(|item| ((if item.is_rtl { item.xmin } else { item.xmax }), item.ymin, item.ymax))
|
||||
})
|
||||
})
|
||||
.or_else(|| boxes.first().map(|item| (item.xmin, item.ymin, item.ymax)));
|
||||
.or_else(|| boxes.first().map(|item| ((if item.is_rtl { item.xmax } else { item.xmin }), item.ymin, item.ymax)));
|
||||
let Some((anchor_x, anchor_y, anchor_top)) = anchor else {
|
||||
return caret.min(visible_count);
|
||||
};
|
||||
|
||||
+22
-7
@@ -141,10 +141,18 @@ impl MTextPreview {
|
||||
let d = dy * 1000.0 + dx; // prefer the correct line first
|
||||
if d < best_d {
|
||||
best_d = d;
|
||||
best = b.vis;
|
||||
// After the glyph centre → caret sits after this char.
|
||||
if wx > (b.xmin + b.xmax) * 0.5 {
|
||||
best = b.vis + 1;
|
||||
if b.is_rtl {
|
||||
if wx < (b.xmin + b.xmax) * 0.5 {
|
||||
best = b.vis + 1;
|
||||
} else {
|
||||
best = b.vis;
|
||||
}
|
||||
} else {
|
||||
best = b.vis;
|
||||
// After the glyph centre → caret sits after this char.
|
||||
if wx > (b.xmin + b.xmax) * 0.5 {
|
||||
best = b.vis + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,14 +288,21 @@ impl iced::widget::canvas::Program<Message> for MTextPreview {
|
||||
);
|
||||
} else if collapsed {
|
||||
let bar = if let Some(b) = self.boxes.iter().find(|b| b.vis == self.caret) {
|
||||
Some((b.xmin, b.ymin, b.ymax)) // left edge of the caret's glyph
|
||||
let cx = if b.is_rtl { b.xmax } else { b.xmin };
|
||||
Some((cx, b.ymin, b.ymax))
|
||||
} else if self.caret > 0 {
|
||||
self.boxes
|
||||
.iter()
|
||||
.find(|b| b.vis == self.caret - 1)
|
||||
.map(|b| (b.xmax, b.ymin, b.ymax)) // after the last glyph
|
||||
.map(|b| {
|
||||
let cx = if b.is_rtl { b.xmin } else { b.xmax };
|
||||
(cx, b.ymin, b.ymax)
|
||||
})
|
||||
} else {
|
||||
self.boxes.first().map(|b| (b.xmin, b.ymin, b.ymax))
|
||||
self.boxes.first().map(|b| {
|
||||
let cx = if b.is_rtl { b.xmax } else { b.xmin };
|
||||
(cx, b.ymin, b.ymax)
|
||||
})
|
||||
};
|
||||
if let Some((cx, y0, y1)) = bar {
|
||||
let p0 = map(cx, y0);
|
||||
|
||||
Reference in new issue
Block a user