How to create a multiline string or multiline label as a CGPath in iOS?

烂漫一生 提交于 2019-12-11 02:24:55

问题


Does the API support this? If not, how could I do it?

There is CTFontCreatePathForGlyph in Core Text, which can translate a single character into a path. I could use that in a loop to create my string as a path, but I'd have to deal with spacing and kerning and all the other nasty things. I'm looking for a string path that would looks the same if it was drawn in a UILabel with same font and size.


回答1:


There is an article called Low-level text rendering by Ohmu that covers this pretty extensively. I have tried this code and can confirm that it works.

It does use Core Text, though, so the rendering is probably not exactly like that of a UILabel. Also, the sample article only deals with a single line. To extend it to multiple lines, you have to setup the complete Core Text system. Instead of:

CTLineRef line = CTLineCreateWithAttributedString( attStr ) ;

you need to set up a CTFramesetterRef (CTFramesetterCreateWithAttributedString) and CTFrameRef (CTFramesetterCreateFrame) as described in the Core Text Programming Guide. You can then get all lines in the frame with CTFrameGetLines().

You would then wrap the for loop in the sample article:

CFArrayRef runArray = CTLineGetGlyphRuns(line);

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

with another loop that iterates over all lines. The inner core of the loop should be identical.

The sample article creates a graphics context and adds the paths for the single glyphs to this context's path, but you can just as easily create a CGMutablePathRef or UIBezierPath and add the single glyph's paths to that object.

One thing that is not 100% clear to me without testing this is how to adjust the vertical position of the glyphs in the final path. You probably have to call CTFrameGetLineOrigins() to get the position of each line and add this position to each rendered glyph (possibly after transforming it with the text matrix).




回答2:


Look at the UIBezierPath+TextPaths category in this project: https://github.com/aderussell/string-to-CGPathRef.

It shows how to create paths for single and multi-line strings and how to use them with CAShapeLayers.

The category is just a wrapper and the internal functions can be used in iOS or Mac OS X, you just need to link your project to the CoreText framework.



来源:https://stackoverflow.com/questions/7573383/how-to-create-a-multiline-string-or-multiline-label-as-a-cgpath-in-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!