react / react/react-native

iOS: nested Text with mixed fonts + lineHeight paints glyphs shifted/clipped under tail truncation — while onTextLayout/onLayout report correct positions

Ouverte
#58,315 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Needs: Triage :mag: Platform: iOS
Langage dominant
C++
Étoiles
127k
Forks
25.3k
Merge moyen
1 j 23 h
PR mergées (30 j)
4

Description

Description

A one-line (Arabic, RTL) containing nested spans where one span uses a different font/size (a fallback-font run), with an explicit lineHeight, paints its glyphs vertically shifted and bottom-clipped when the line is tail-truncated on iOS. Untruncated rows with identical structure paint correctly. The shift worsens with scroll depth in a ScrollView.

Reproduces across fonts: dramatic with a mushaf-grade face (KFGQPC Hafs — glyphs sink and bottom-clip), subtle but present with Scheherazade New (descender marks such as hamza+kasra paint slightly low). Severity scales with how far the font's ink extents diverge from its nominal metrics.

Critically: the shift is invisible to the layout APIs. onLayout and onTextLayout report identical geometry for shifted and correct rows — the repro measures both and prints the delta, which reads 0.0px while the painted output visibly diverges (the label is kept as a negative control). The defect appears to sit between text layout and rendering.

Plain single-font rows, flat rows, narrow rows, and RTL-aligned rows all paint correctly (mutations M1–M3 in the repro, all Δ 0.0 and visually clean) — the mixed-font nested run (M4) is the trigger.

Possibly related: #19653 (baseline offset computed from largest font-height in the string), #53092 (nested Text misalignment with lineHeight under the New Architecture).

Screenshots (also in the repo README): truncated rows sinking/clipping under Hafs+M4 vs their fitting pair rows.

Steps to reproduce

Reproduces across fonts: dramatic with a mushaf-grade face (KFGQPC Hafs — glyphs sink and bottom-clip), subtle but present with Scheherazade New (descender marks such as hamza+kasra paint slightly low). Severity scales with how far the font's ink extents diverge from its nominal metrics.

  1. Clone https://github.com/muhasabahhub/rn-arabic-seat, npm install, npx expo start, open in Expo Go on a physical iPhone.
  2. Select: tail (stock) + Hafs (mushaf) + M4 mixed-run.
  3. Scroll the list. Rows come in pairs sharing their opening words — first fits, second truncates.
  4. Compare pairs against the red guide: truncated rows paint shifted/bottom-clipped, worsening with scroll depth.
  5. Note the Δ label reads 0.0px — onLayout/onTextLayout report identical seating while the paint diverges (negative control).
  6. Toggle M4 off (or fonts to Amiri): all rows paint correctly, Δ 0.0 and visually clean.
React Native Version

0.86.3

Affected Platforms

Runtime - iOS

Output of npx @react-native-community/cli info
Expo SDK 57 managed project — envinfo equivalent below; full dependency table in the repo README.

 System:
    OS: Windows 11 10.0.26200
    CPU: (22) x64 Intel(R) Core(TM) Ultra 7 155H
    Memory: 3.80 GB / 15.59 GB
  Binaries:
    Node: 24.13.1 - C:\Program Files\nodejs\node.EXE
    npm: 11.19.0 - C:\Program Files\nodejs\npm.CMD
  npmPackages:
    expo: ~57.0.18 => 57.0.19
    expo-font: ~57.0.2 => 57.0.3
    react: 19.2.3 => 19.2.3
    react-native: 0.86.3 => 0.86.3
    react-native-safe-area-context: ~5.7.0 => 5.7.0


Device: iPhone 15, iOS 23.3.1, physical device via Expo Go. New Architecture (Fabric), Hermes.
Stacktrace or Logs
No crash or error output — this is a silent rendering defect. Nothing is logged.

The relevant "log" is the measurement built into the repro itself: each row pair prints a Δ label computed from onLayout + onTextLayout. For visibly shifted rows, the APIs report Δ 0.0px — i.e. the layout system emits no signal that the painted output has diverged. Sample readout while the defect is visible on screen:

  pair 3 (Hafs, tail, M4): reported Δ 0.0px — painted output shifted and bottom-clipped (screenshot 1)
  pair 5 (Hafs, tail, M4): reported Δ 0.0px — painted output shifted, worsens with scroll depth (screenshot 2)

The absence of any discrepancy in the layout events is part of the report: the defect is undetectable programmatically from the JS layer.
MANDATORY Reproducer

https://github.com/muhasabahhub/rn-arabic-seat

Screenshots and Videos
Image

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par le reproducer obligatoire rn-arabic-seat, exécutez-le sur un iPhone physique et comparez les lignes M4 tail-truncated utilisant Hafs ou Scheherazade New avec les lignes de contrôle correspondantes. Aucun fichier source ni test React Native n’est nommé ; le travail est considéré comme terminé lorsque les lignes RTL à polices mixtes ne sont plus rendues décalées ou coupées en bas sous tail truncation, tandis que la géométrie de layout signalée reste correcte.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
ios, react-native
Domaine
mobile
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
38/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.