V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
kobe1941
V2EX  ›  iDev

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

  •  
  •   kobe1941 · 2015-05-26 17:16:41 +08:00 · 4629 次点击
    这是一个创建于 3501 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题,CoreText进行中英文混排时,CTLine的行高不一致,这样子不好看,请问有什么解决的方式么?

    效果见图:
    7 条回复    2015-05-27 14:38:39 +08:00
    kobe1941
        1
    kobe1941  
    OP
       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
        2
    wdxz5586  
       2015-05-26 17:33:45 +08:00   ❤️ 1
    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
        3
    kobe1941  
    OP
       2015-05-26 17:52:45 +08:00
    @wdxz5586 你好,可以详细说下第四个步骤的计算公式么?
    kobe1941
        4
    kobe1941  
    OP
       2015-05-26 19:09:18 +08:00
    @wdxz5586 我搞错了CoreText的绘制的原点问题,原来绘制的origin是在baseLine,调整后得到的预期的效果,谢谢啊。

    不过这样子调整的话,因为CoreText本身就是英文字符比中文字符高,排版看起来不大美观,估计要美观的话只好指定每一行的确切高度了。我们现在在处理时如果调整的字体大小,那么指定的行高需要重新再设置,感觉有点麻烦,不知你有没其他好方案?
    wdxz5586
        5
    wdxz5586  
       2015-05-26 21:49:05 +08:00
    可以尝试调整一下 paragraphStyle
    galenzhao
        6
    galenzhao  
       2015-05-27 10:03:36 +08:00
    kobe1941
        7
    kobe1941  
    OP
       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;
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5555 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 54ms · UTC 03:36 · PVG 11:36 · LAX 19:36 · JFK 22:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.