CoreText 怎么解决中英文字符行高不一致的问题?

2015-05-26 17:16:41 +08:00
 kobe1941
如题,CoreText进行中英文混排时,CTLine的行高不一致,这样子不好看,请问有什么解决的方式么?

效果见图:
4412 次点击
所在节点    iDev
7 条回复
kobe1941
2015-05-26 17:25:35 +08:00
我们现在有一种很怪异的实现方式,就是不管是中文,英文还是中英文混合的CTLine,在字体大小确定的情况下,设定每一行的高度为一个固定值,这样子在绘制的时候一行一行的去CTLineDraw绘制,绘制之前再微调Y值,反正每一行的行高都是确定的,绘制起来也方便,只是感觉这种方式怪怪的,非主流。

这种方式在这里也有介绍: https://twitter.com/tualatrix/status/433625806678417408


另外有人解决了emoji排版的行间距的问题,http://www.minroad.com/?p=776,我照着他的方式试了下,好像解决不了中英文的排版行高问题。
wdxz5586
2015-05-26 17:33:45 +08:00
1. 取到对应的 UIFont 的 Ascent,Descent,Leading 值(A/D/L)
2. 通过 CTLineGetTypographicBounds 取到每一行对应的 A/D/L
3. 通过 CTFrameGetLineOrigins 取到每一行对应的 origin
4. 根据两个 A/D/L 计算 origin.y 调整的幅度
5. 绘制时通过 CGContextSetTextPosition 重新设置每一行的 origin
kobe1941
2015-05-26 17:52:45 +08:00
@wdxz5586 你好,可以详细说下第四个步骤的计算公式么?
kobe1941
2015-05-26 19:09:18 +08:00
@wdxz5586 我搞错了CoreText的绘制的原点问题,原来绘制的origin是在baseLine,调整后得到的预期的效果,谢谢啊。

不过这样子调整的话,因为CoreText本身就是英文字符比中文字符高,排版看起来不大美观,估计要美观的话只好指定每一行的确切高度了。我们现在在处理时如果调整的字体大小,那么指定的行高需要重新再设置,感觉有点麻烦,不知你有没其他好方案?
wdxz5586
2015-05-26 21:49:05 +08:00
可以尝试调整一下 paragraphStyle
galenzhao
2015-05-27 10:03:36 +08:00
kobe1941
2015-05-27 14:38:39 +08:00
@galenzhao 谢谢,不过这个我试过了,如果单纯按照他的方式来计算,是不行的,

这个计算公式:
lineOrigin.y = lineOrigin.y - descent - self.font.descender;

并不能保证绘制出来每行的高度间距一致,因为中英文CTLine的ascent,descent都不一样。不过倒是效果跟我的这个计算方式一样了:

if (i > 0)
{
// 第二行之后需要计算
frameY = frameY - globalLineLeading - lineAscent;

lineOrigin.y = frameY;

} else
{
// 第一行可直接用
frameY = lineOrigin.y;
}

// 调整坐标
CGContextSetTextPosition(contextRef, lineOrigin.x, lineOrigin.y);
CTLineDraw(line, contextRef);

// 微调
frameY = frameY - lineDescent;

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/193883

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX