【问题标题】:How to create a multiline string or multiline label as a CGPath in iOS?如何在 iOS 中创建多行字符串或多行标签作为 CGPath?
【发布时间】:2023-03-27 18:26:01
【问题描述】:

API 是否支持此功能?如果没有,我该怎么做?

Core Text中有CTFontCreatePathForGlyph,可以将单个字符翻译成路径。我可以在循环中使用它来创建我的字符串作为路径,但我必须处理间距和字距调整以及所有其他讨厌的事情。我正在寻找一个字符串路径,如果它是在具有相同字体和大小的 UILabel 中绘制的,则看起来相同。

【问题讨论】:

    标签: ios text core-graphics cgpath


    【解决方案1】:

    Ohmu 有一篇名为 Low-level text rendering 的文章对此进行了广泛的介绍。我已经尝试过这段代码并且可以确认它有效。

    不过,它确实使用了 Core Text,因此渲染可能与 UILabel 的渲染不完全相同。此外,示例文章仅处理一行。要将其扩展到多行,您必须设置完整的 Core Text 系统。而不是:

    CTLineRef line = CTLineCreateWithAttributedString( attStr ) ;
    

    您需要按照核心文本编程指南中的说明设置CTFramesetterRef (CTFramesetterCreateWithAttributedString) 和CTFrameRef (CTFramesetterCreateFrame)。然后,您可以使用CTFrameGetLines() 获取框架中的所有行。

    然后您将在示例文章中包装 for 循环:

    CFArrayRef runArray = CTLineGetGlyphRuns(line);
    
    // for each RUN
    for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++)
    

    使用另一个循环遍历所有行。循环的内核应该是相同的。

    示例文章创建了一个图形上下文并将单个字形的路径添加到此上下文的路径中,但您也可以轻松创建 CGMutablePathRefUIBezierPath 并将单个字形的路径添加到该对象。

    在没有测试的情况下,我并不是 100% 清楚这一点,那就是如何调整最终路径中字形的垂直位置。您可能必须调用 CTFrameGetLineOrigins() 来获取每行的位置并将该位置添加到每个呈现的字形(可能在使用文本矩阵对其进行转换之后)。

    【讨论】:

    • 我浏览了该代码,但找不到可以访问单个字形以构建字形多行路径的部分。
    • 你是对的,该代码只处理一行文本。我将编辑我的答案以扩展它(可能需要一些时间)。
    【解决方案2】:

    查看本项目中的 UIBezierPath+TextPaths 类别:https://github.com/aderussell/string-to-CGPathRef

    它展示了如何为单行和多行字符串创建路径以及如何将它们与 CAShapeLayers 一起使用。

    类别只是一个包装器,内部函数可以在iOS或Mac OS X中使用,您只需要将您的项目链接到CoreText框架。

    【讨论】:

      猜你喜欢
      • 2012-07-23
      • 2019-04-24
      相关资源
      最近更新 更多