iOS: nested Text with mixed fonts + lineHeight paints glyphs shifted/clipped under tail truncation — while onTextLayout/onLayout report correct positions
まだ誰も着手していません。
- 主要言語
- C++
- スター
- 127k
- フォーク
- 25.3k
- 平均マージ
- 1日 23時間
- マージ済み PR(30日)
- 4
説明
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.
- Clone https://github.com/muhasabahhub/rn-arabic-seat, npm install, npx expo start, open in Expo Go on a physical iPhone.
- Select: tail (stock) + Hafs (mushaf) + M4 mixed-run.
- Scroll the list. Rows come in pairs sharing their opening words — first fits, second truncates.
- Compare pairs against the red guide: truncated rows paint shifted/bottom-clipped, worsening with scroll depth.
- Note the Δ label reads 0.0px — onLayout/onTextLayout report identical seating while the paint diverges (negative control).
- 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
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
必須の rn-arabic-seat reproducer から始め、物理 iPhone で実行し、Hafs または Scheherazade New を使用した tail-truncated M4 行を、対応する制御行と比較します。React Native のソースファイルやテストは指定されていません。完了とは、報告されたレイアウトジオメトリが正しいまま、tail truncation の下で混在フォントの RTL 行がずれて描画されたり下端でクリップされたりしなくなることです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- ios, react-native
- 領域
- mobile
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 活発
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 38/100