卡死 App 的神秘字符串,究竟是何方神圣(下)

一、卡死 App 字符串的神秘之处

延续上篇的内容,本文将继续分析神秘字符串导致 App 卡死的问题。

在继续翻阅源码和 Debug 的过程中,我们会遇到几个概念,比如 runs 和 level,在 getOffsetBeforeAfter 的入参也能看到它们。

在继续分析这个问题之前,我们先来了解几个关于文字排版的基础知识,以帮助我们更加顺畅地理解后面的分析过程。

这部分包含对网络资料的摘录整理以及一些个人的理解,如有纰漏还请老铁们不吝赐教。

Unicode 断行算法

断行是为了在显示一长串文字时能够自动换行 (在没有明确的换行符的情况下),比如对于同一段文字,我们调整 TextView 的宽度时会呈现不同的显示。但它并不是完全按照文字的宽度紧密排布的,而是有一套断行算法:告诉你什么时候必须断行,什么时候可以断行以及什么时候不能断行等。

算法的完整定义在这里:

UAX #14: Unicode Line Breaking Algorithm[1]

图片

图片

 

如上图所示,我们不断调整 TextView 的宽度,会发现自动换行时候的一些特点,比如对中文而言,书名号右半部分始终与其左边的文字一起换行,而英文单词基本上不会被拆分换行,这些都是由断行算法所定义的。

断行算法的核心逻辑是对所有字符归类,然后根据一定的规则判断字符间是否可以换行,其主要用途在于解析出给定字符串可以换行的地方。这里我们不对算法做过多的解析,下面给出几条其中的规则,第一条是后文分析中最为重要的一条:

○ 英语字母与空格一起时允许空格后面换行

○ 当英语字母处于破折号前面时不允许换行,允许在其后面换行;如果破折号后面是数字的话则不允许换行

○ 当左括号后面接着英语字母或者数字时不允许换行;当英语字母或者数字紧挨着右括号时不允许换行

Unicode 双向算法 (Bidi 算法)

大部分语言的文本在水平方向上都是按照从左到右 (Left To Right,简称 LTR) 的顺序显示字符的,但是也有不少语言是按照从右到左 (Right To Left,简称 RTL)的顺序。最简单的情况是一段文字里面只有一个方向,但在实际情况中,也存在一个字符串中同时包含 LTR 和 RTL 的文本,这就是双向文本。双向算法即用来处理双向文本的排版。

算法的完整定义在这里 :

UAX #9: Unicode Bidirectional Algorithm[2]

Bidi 算法把每一个字符进行了分类(Category),包括强字符、弱字符、中性字符等,每一种分类又有不同的类型(Type)。其中强字符表示它具有明确的方向信息,并且会影响其前后的中性字符的方向。

比如,中文汉字就是强字符,类型为 L;阿拉伯语、希伯来语也是强字符,类型为 R;空格为中性字符,而数字英文句号和逗号等为弱字符。这里的 L 也是 Left To Right 的意思,但和前面的 LTR 不是用来表达同一个事情:LTR 更多用来表示一段文字的方向,而 L 和 R 用来表示一个字符的类型(Type),如 L 表示强字符分类中类型为从左向右的字符。

另外 ,Bidi 类型不止 L 和 R,还有 AL、EN 等,详见 Bidirectional Character Types[3]。

除了以上三种字符分类外,还有一类“定向格式化字符” (也可以叫作“显式格式码”),如图 2 中的 RLE 和 PDF,可以用来控制或改变其他字符的显示顺序 (注意只影响显示顺序,其他方面比如文本比较、断句、词法分析等影响都会被忽略)。

这里再介绍几个概念,在后续的代码分析过程中也会涉及到:

○ 嵌入等级(level)

也称嵌入水平,表示字符的嵌入层次,数字越大嵌入得越深。在Bidi算法中,字符串中的每个字符都有一个嵌入等级。

○ 基础方向(base direction)

分段的方向被称为基础方向,它决定了该段文本从左侧还是右侧开始书写。

○ 运行等级(level r

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值