ZWJ emoji sequences break apart in vertical writing modes

#41384307 Filed 2018-04-19 P3 / S5 Still reproducible on Chrome 154

Repro steps

Minimal case

1. Render an emoji ZWJ sequence, for example U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 (MAN ZWJ WOMAN ZWJ GIRL ZWJ BOY).

2. Put it in an element with writing-mode: vertical-rl (or the legacy tb-rl) and the default text-orientation: mixed.

3. Compare against the same string in horizontal-tb.

Expected vs actual

Expected: one combined glyph, the same cluster the horizontal case produces.

Actual: the sequence falls apart into its component emoji, stacked as separate characters.

Samples

Rendered is live in your browser. Expected is a content_shell baseline with the patch applied. Diff highlights the pixels the patch changes relative to an unpatched build.

Family: MAN ZWJ WOMAN ZWJ GIRL ZWJ BOY

writing-mode: vertical-rl vs horizontal-tb

vertical-rl
👨‍👩‍👧‍👦
vertical-lr
👨‍👩‍👧‍👦
tb-rl (legacy)
👨‍👩‍👧‍👦
horizontal-tb
👨‍👩‍👧‍👦

On an unpatched build the three vertical columns show four separate emoji; the horizontal one shows a single family glyph.

Patched baseline for the family sequence
Diff between unpatched and patched for the family sequence

Kiss: WOMAN ZWJ HEART VS16 ZWJ KISS MARK ZWJ MAN

ZWJ sequence that also contains a variation selector

vertical-rl
👩‍❤️‍💋‍👨
horizontal-tb
👩‍❤️‍💋‍👨
Patched baseline for the kiss sequence
Diff between unpatched and patched for the kiss sequence

Pirate flag, polar bear, professions

PIRATE FLAG, POLAR BEAR, WOMAN TECHNOLOGIST, MAN FARMER

vertical-rl
🏴‍☠️🐻‍❄️
vertical-rl
👩‍💻👨‍🌾
horizontal-tb
🏴‍☠️🐻‍❄️👩‍💻👨‍🌾
Patched baseline for pirate flag, polar bear and profession sequences
Diff between unpatched and patched for pirate flag, polar bear and profession sequences

Non-emoji ZWJ must keep rotating

a<ZWJ>b and a Devanagari half-form U+0915 U+094D U+200D U+0937 still follow UAX #50 for their own characters

latin + zwj
a‍b‍c
devanagari + zwj
क्‍ष
emoji then latin
👩‍b

Glyph selection is unchanged. The third cell shifts by a sub-pixel because GB9 moves the zero-width joiner from the rotated run into the upright emoji run.

Patched baseline for non-emoji ZWJ controls
Diff between unpatched and patched for non-emoji ZWJ controls