引擎 3.8.8
设备情况
- 正常设备: android windows上全部正常
正常的iphone设备
- iPhone 16 pro max
- ihpone 12 pro
异常的iphone设备:
- iPhone13
- iPhone14
- iPhone15
- iPhone16 pro
缅文显示截图:
- 正常显示
- 异常显示
- char 缓存模式显示
原因分析
缅文异常不是单点问题,而是几条链路叠加出来的:
-
字形测量不稳定
在 iPhone Safari 上,Canvas 的 measureText、actualBoundingBoxLeft、actualBoundingBoxRight 对缅文组合字形并不稳定,尤其是带前置元音、叠写和组合附标时,测量宽度和真实可见宽度会不一致。相关测量入口在 text-utils.ts safeMeasureText -
原始断行策略不适合缅文
普通断行更接近“按字符/单词宽度贪心切分”,但缅文很多显示单元是音节簇,不能随意拆开。拆簇后会出现一部分留在上一行、一部分掉到下一行,直接导致观感错误和局部裁切。相关断行逻辑集中在 text-utils.ts safeMeasureText -
iPhone 专用安全补偿过于保守
为了避免 Safari 低估缅文宽度,safeMeasureText 对 iPhone 缅文额外加了宽度补偿。这能减少裁切,但也会带来过早换行、右侧留白变大。补偿逻辑在text-utils.ts safeMeasureText -
对齐语义和实际绘制语义不一致
在修复过程中确认,iOS 缅文场景下单纯依赖 Canvas 的 center、right 对齐不稳定。即使起点算对了,浏览器也可能仍按 left 的视觉结果去画,导致“设置居中却像左对齐”“设置右对齐却位置错误”。绘制主链路在 text-processing.ts _calculateFillTextStartPosition -
padding 与可见边界不是一回事
原本很多起点计算基于 canvasPadding 和逻辑宽度,但缅文字形常常存在左外扩、右外扩,真正应该对齐的是“可见边界”,不是逻辑 advance width。这也是后来 CENTER、RIGHT 都需要改成按 bbox 手算的原因。
修复思路
整体思路分三层:
- 先保证“能正确显示”
优先解决裁切、断行拆簇、整行错位。也就是先让文本内容完整、可读,不先追求完全精确的视觉居中。 - 再把“测量”和“绘制”拆开处理
safeMeasureText 适合做保护性测量,避免裁切;但不适合直接拿来做 CENTER、RIGHT 的精确视觉定位。
所以后续改成:
- 换行和左侧保护需要时保留安全补偿
- CENTER、RIGHT 的最终绘制位置改为基于真实 bbox 手算
- 对 iOS 缅文单独走手动对齐
不再完全依赖 Canvas 的 textAlign=center 或 textAlign=right,而是:
- CENTER:按每行可见宽度手动算出左起点
- RIGHT:按每行可见右边界手动算出左起点
这样能绕开 Safari 对缅文的对齐不稳定问题。
修复过程
- 梳理显示链路
先确认 TTF 文本在引擎里的主要流程:
- 文本处理、换行、尺寸计算在 text-processing.ts _calculateFillTextStartPosition
- 文本测量和分段在 text-utils.ts safeMeasureText
- 入口调度在 ttfUtils.ts
- 修正缅文断行
在 text-utils.ts safeMeasureText 里补充了缅文相关规则:
- 行首禁断/行尾禁断
- 音节簇边界识别
- 缇文整簇分割与整簇下移
这一步主要解决“不能拆簇”和“断行观感错误”。
-
修正 RESIZE_HEIGHT 的结构性问题
中途发现 RESIZE_HEIGHT 场景曾把宽度也带偏了,后面恢复为只改高度,避免宽度基准持续漂移。对应逻辑在 text-processing.ts _calculateFillTextStartPosition。 -
处理 iPhone 缅文左侧/右侧裁切
在 LEFT 对齐场景,对绘制起点增加了左边界保护和右边界保护,优先保证左侧不被裁,再尽量压缩右侧空白。这部分仍保留在 text-processing.ts _updateTexture 。 -
降低过早换行
为了减少“明明还能放下却提前换到下一行”的情况,把部分断行测量从带额外补偿的保守测量,改成更紧凑的测量思路。核心目标是把“换行判定”和“绘制安全边距”解耦。 -
修复 CENTER 对齐异常
后面确认 CENTER 的根因不是单纯起点公式,而是浏览器对缅文 center 绘制语义不可靠。
最终处理方式是:
- iOS 缅文 + CENTER 时,绘制语义切到 left
- 再按每一行的实际可见宽度和 bbox 手动计算起点
相关逻辑在 text-processing.ts _updateTexture。
- 修复 RIGHT 对齐异常
RIGHT 最后也采用了和 CENTER 同样的策略:
- 不再依赖 Safari 的 right 对齐
- 改成按每行真实可见边界手算左起点
相关逻辑在 text-processing.ts _updateTexture。
将代码覆盖到
resources/resources/3d/engine/cocos/2d
2d.zip (247.4 KB)
申明
- 参照开源协议MIT
