上一讲我们介绍了如何获取文本字符,这一讲介绍文本的布局
我们之前在2019-7-29-WPF文本(1)-当显示文本时我们到底在做什么(1) - huangtengxiao介绍过,文本渲染需要经历找字符、measure、arrange、render过程。这里我们统一介绍measure和arrange过程(Layout过程)
Layout
首先我们思考下一群文本字符应该怎么对齐呢?上对齐?下对齐?
并不是,这群文字采用了一种奇妙的对齐方式,按照红线的那种不上不下的对齐,Baseline对齐

什么是baseline呢,简单来说就是用于文本对齐的基准。毕竟不是所有的文字都和汉字一样写的方方正正的,还是有一些语言的布局为了整体的美观需要各个字符能够上下调节。所以基线能够控制字符的对齐。
有了基线还有什么呢?有的同学马上说到width和height。
有同学说这个这么简单,需要讲么?需要。
我们看看下面的图片。f的选择宽度要远小于字符的呈现宽度,而f的呈现大小“入侵”了其他字符的区域。因此简单的width和height肯定不能满足这些需求。


我们看下软件中字符的各个尺寸表示,以WPF为例。下图的black box指的是字符的显示图像的大小,或者说这个字符的Geometry.Bounds。中间的横线就是字符的Baseline,用于字符的对齐。而Advance Width则是我们选择时看到的宽度,或者说是整个字符在文本中布局使用的宽度。而字符图形在渲染时的相对位置则是由left side bearing, Right side bearing, Upright baseline offset共同确定的。

由此,我们可以确定:
- 字符的布局宽度(advance width)=左侧偏移(left side bearing)+右侧偏移(Right side bearing)+字符图像宽度
- 字符的布局高度(advance height)=字符图像高度+竖直偏移(Upright baseline offset)
- 字符布局位置由baseline origin确定
那么这么多的数据应该放在哪里呢?当然是放在字体文件的元数据中咯,这样就可以大幅减少软件层面的计算量。
OK,花了大力气介绍单个字符的布局,那么多行,多段落就会相对简单。他们和我们普通元素布局类似,只要指定位置将字符一个个"码"上去就行了。
参考链接: