fix: find decoration spans in bidi text
This commit is contained in:
parent
0666ba14b1
commit
b0884c0ab1
6 changed files with 64 additions and 17 deletions
|
|
@ -276,6 +276,9 @@ pub struct GlyphDecorationData {
|
|||
pub underline_metrics: DecorationMetrics,
|
||||
/// Strikethrough offset and thickness from the font
|
||||
pub strikethrough_metrics: DecorationMetrics,
|
||||
/// Font ascent in EM units (ascent / upem).
|
||||
/// Used for overline positioning
|
||||
pub ascent: f32,
|
||||
}
|
||||
|
||||
/// Text attributes
|
||||
|
|
|
|||
|
|
@ -115,9 +115,8 @@ fn draw_decoration_span<R: Renderer>(
|
|||
let thickness = (deco.underline_metrics.thickness * font_size)
|
||||
.max(1.0)
|
||||
.ceil();
|
||||
//TODO: this should be run.line_y - ascent, but we don't have per-glyph ascent
|
||||
// in LayoutGlyph. Using line_top as an approximation for now.
|
||||
let y = run.line_top;
|
||||
// clamped so it doesn't go above the line top.
|
||||
let y = (run.line_y - deco.ascent * font_size).max(run.line_top);
|
||||
renderer.rectangle(x_start as i32, y as i32, w, thickness as u32, color);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
src/shape.rs
27
src/shape.rs
|
|
@ -612,11 +612,15 @@ impl ShapeGlyph {
|
|||
}
|
||||
}
|
||||
|
||||
fn decoration_metrics(font: &Font) -> (DecorationMetrics, DecorationMetrics) {
|
||||
fn decoration_metrics(font: &Font) -> (DecorationMetrics, DecorationMetrics, f32) {
|
||||
let metrics = font.metrics();
|
||||
let upem = metrics.units_per_em as f32;
|
||||
if upem == 0.0 {
|
||||
return (DecorationMetrics::default(), DecorationMetrics::default());
|
||||
return (
|
||||
DecorationMetrics::default(),
|
||||
DecorationMetrics::default(),
|
||||
0.0,
|
||||
);
|
||||
}
|
||||
(
|
||||
DecorationMetrics {
|
||||
|
|
@ -627,10 +631,11 @@ fn decoration_metrics(font: &Font) -> (DecorationMetrics, DecorationMetrics) {
|
|||
offset: metrics.strikeout.map_or(0.3, |d| d.offset / upem),
|
||||
thickness: metrics.strikeout.map_or(1.0 / 14.0, |d| d.thickness / upem),
|
||||
},
|
||||
metrics.ascent / upem,
|
||||
)
|
||||
}
|
||||
|
||||
/// span index used in VlRange to indicate this range is the ellipsis.
|
||||
/// span index used in `VlRange` to indicate this range is the ellipsis.
|
||||
const ELLIPSIS_SPAN: usize = usize::MAX;
|
||||
|
||||
fn shape_ellipsis(
|
||||
|
|
@ -1046,7 +1051,7 @@ impl ShapeSpan {
|
|||
.map(|font| decoration_metrics(&font))
|
||||
});
|
||||
|
||||
if let Some((ul_metrics, st_metrics)) = primary_metrics {
|
||||
if let Some((ul_metrics, st_metrics, ascent)) = primary_metrics {
|
||||
// Track which sub-ranges of span_range are covered by explicit spans
|
||||
let mut covered_end = span_range.start;
|
||||
|
||||
|
|
@ -1068,6 +1073,7 @@ impl ShapeSpan {
|
|||
text_decoration: default_attrs.text_decoration,
|
||||
underline_metrics: ul_metrics,
|
||||
strikethrough_metrics: st_metrics,
|
||||
ascent,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
@ -1082,6 +1088,7 @@ impl ShapeSpan {
|
|||
text_decoration: attrs.text_decoration,
|
||||
underline_metrics: ul_metrics,
|
||||
strikethrough_metrics: st_metrics,
|
||||
ascent,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
@ -1097,6 +1104,7 @@ impl ShapeSpan {
|
|||
text_decoration: default_attrs.text_decoration,
|
||||
underline_metrics: ul_metrics,
|
||||
strikethrough_metrics: st_metrics,
|
||||
ascent,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
@ -2081,7 +2089,7 @@ impl ShapeLine {
|
|||
.map_or(0.0, |s| s.words.iter().map(|w| w.width(font_size)).sum())
|
||||
}
|
||||
|
||||
/// Creates a VlRange for the ellipsis with the given BiDi level.
|
||||
/// Creates a `VlRange` for the ellipsis with the give`BiDi`Di level.
|
||||
fn ellipsis_vlrange(&self, level: unicode_bidi::Level) -> VlRange {
|
||||
VlRange {
|
||||
span: ELLIPSIS_SPAN,
|
||||
|
|
@ -2091,7 +2099,7 @@ impl ShapeLine {
|
|||
}
|
||||
}
|
||||
|
||||
/// Determines the appropriate BiDi level for the ellipsis based on the
|
||||
/// Determines the appropriate `BiDi` level for the ellipsis based on the
|
||||
/// adjacent ranges, following UAX#9 N1/N2 rules for neutral characters.
|
||||
fn ellipsis_level_between(
|
||||
&self,
|
||||
|
|
@ -2860,11 +2868,8 @@ impl ShapeLine {
|
|||
}
|
||||
glyphs.push(layout_glyph);
|
||||
|
||||
// Advance (or reset) the decoration cursor to find
|
||||
// the span covering this glyph's byte position.
|
||||
// Resets for RTL/BiDi where byte order reverses.
|
||||
if deco_cursor < deco_spans.len()
|
||||
&& glyph.start < deco_spans[deco_cursor].0.start
|
||||
if deco_cursor >= deco_spans.len()
|
||||
|| glyph.start < deco_spans[deco_cursor].0.start
|
||||
{
|
||||
deco_cursor = 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue