Summary
The kerning support added in #1035 (released in 0.4.15, partial DPI fix in #1039) adds the kerning offset to dest.x unconditionally, ignoring TextParams.rotation. For non-zero rotation the offset lands perpendicular to the text-flow axis instead of along it, so each kerned pair shifts the following glyph sideways from its line.
Reproduction
Any draw_text_ex call with TextParams.rotation != 0 and a font that has kerning entries between consecutive glyphs in the rendered string. Concrete repro with OstrichSans-Heavy at rotation = π / 2: the AT / TE / PA pairs that gap horizontally at rotation = 0 now produce vertical-in-screen-space misalignment instead — visible as a per-character perpendicular shift that varies with the surrounding kerning context (the same letter in two different words shifts by different amounts).
Cause
In src/text.rs::draw_text_ex (current master):
let rot_cos = rot.cos();
let rot_sin = rot.sin();
let dest_x = (offset_x + total_width) * rot_cos + (glyph_scaled_h + offset_y) * rot_sin;
let dest_y = (offset_x + total_width) * rot_sin + (-glyph_scaled_h - offset_y) * rot_cos;
let dest = Rect::new(
dest_x / dpi_scaling + x + kerning_offset / dpi_scaling, // ← always +X
dest_y / dpi_scaling + y, // never +Y
...
);
(offset_x + total_width) is the cumulative advance along the unrotated text-flow direction (+X in glyph-local space). The rotation matrix correctly routes it into dest_x / dest_y per the rotation angle. But kerning_offset is an additional text-flow advance and gets bolted onto dest.x without the same rotation routing — so at rotation = π / 2 it lands on screen-Y (perpendicular to flow) instead of screen-X.
Affected platforms
Anywhere draw_text_ex is called with non-zero TextParams.rotation AND the font has kerning entries between consecutive glyphs. Platform-independent — fontdue's kerning data is loaded the same way on every platform that miniquad supports.
Fix
One-line — project kerning_offset onto the rotated text-flow axis before adding it:
let kerning_logical = kerning_offset / dpi_scaling;
let dest = Rect::new(
dest_x / dpi_scaling + x + kerning_logical * rot_cos,
dest_y / dpi_scaling + y + kerning_logical * rot_sin,
...
);
PR follows.
Summary
The kerning support added in #1035 (released in 0.4.15, partial DPI fix in #1039) adds the kerning offset to
dest.xunconditionally, ignoringTextParams.rotation. For non-zero rotation the offset lands perpendicular to the text-flow axis instead of along it, so each kerned pair shifts the following glyph sideways from its line.Reproduction
Any
draw_text_excall withTextParams.rotation != 0and a font that has kerning entries between consecutive glyphs in the rendered string. Concrete repro with OstrichSans-Heavy atrotation = π / 2: theAT/TE/PApairs that gap horizontally atrotation = 0now produce vertical-in-screen-space misalignment instead — visible as a per-character perpendicular shift that varies with the surrounding kerning context (the same letter in two different words shifts by different amounts).Cause
In
src/text.rs::draw_text_ex(currentmaster):(offset_x + total_width)is the cumulative advance along the unrotated text-flow direction (+X in glyph-local space). The rotation matrix correctly routes it intodest_x/dest_yper the rotation angle. Butkerning_offsetis an additional text-flow advance and gets bolted ontodest.xwithout the same rotation routing — so atrotation = π / 2it lands on screen-Y (perpendicular to flow) instead of screen-X.Affected platforms
Anywhere
draw_text_exis called with non-zeroTextParams.rotationAND the font has kerning entries between consecutive glyphs. Platform-independent — fontdue's kerning data is loaded the same way on every platform that miniquad supports.Fix
One-line — project
kerning_offsetonto the rotated text-flow axis before adding it:PR follows.