如何管理文本字形边界 [英] How to manage text glyph boundary
问题描述
UILabel
,则会在字形周围插入空格。以下是显示两个标签的示例,两个标签的字体相同但字符不同。希伯来语数字看起来都比阿拉伯数字短。有没有一种方法来确定字形的大小或以某种方式将字形推出适合框架? < a href =https://i.stack.imgur.com/TkT5y.png =nofollow noreferrer>
正如你所看到的,尽管被添加到一个更高的UILabel中,希伯来数字更短。
编辑:自发布以来,我做了第一遍使用核心文本,看看是否可以解决我的问题。它似乎不会。请参阅将希伯来字形与阿拉伯数字字形进行比较的插图。他们黄色是标签界限。绿色是由核心文本报告的字形矩形。我希望能得到一个矩形的字形齐平,但它看起来像希伯来字形包括上面和旁边的空间,我希望是字形。还有什么我应该检查?
不知道你使用Obj-C还是Swift,但是你可以把它粘贴到Swift Playground页面来查看结果:
导入UIKit
导入CoreText
导入PlaygroundSupport
class PathView:UIView {
var myPath:UIBezierPath?
重写func draw(_ rect:CGRect){
如果让pth = myPath {
UIColor.red.setStroke()
//字形路径被倒置,所以垂直翻转
let flipY = CGAffineTransform(scaleX:1,y:-1.0)
//字形路径可能偏移x coord和高度(因为它被翻转)
let translate = CGAffineTransform(translationX:-pth.bounds.origin.x,y:pth.bounds.size.height + pth.bounds.origin.y)
//应用变换
pth.apply(flipY)
pth.apply(translate)
//笔画路径
pth.stroke()
//打印修改/引用的路径
print(pth)
}
}
class TestViewController:UIViewController {
override func viewDidLoad(){
super.viewDidLoad()
//蓝色背景,所以我们可以看到框架
view.backgroundColor = UIColor(红色:0.25,绿色:0.5,蓝色:01.0,alpha:1.0)
//使用大字体,这样我们可以很容易地看到
let font = UIFont(name:Times,size:160)!
//希伯来字符8
var unichars = [UniChar](ח。utf16)
unichars = [UniChar](י。utf16)
// init字形数组
var glyphs = [CGGlyph](repeatElement(0,count:unichars.count))
getGlyphs = CTFontGetGlyphsForCharacters(font,& unichars ,& glyphs,unichars.count)
如果gotGlyphs {
//获取cgPath为字符
let cgpath = CTFontCreatePathForGlyph(font,glyphs [0],nil) !
//将其转换为UIBezierPath
让路径= UIBezierPath(cgPath:cgpath)
var r = path.bounds
//让我们在40,40
r = r.offsetBy(dx:40.0,dy:40.0)
让pView = PathView(frame:r)
pView.backgroundColor = .white
pView.myPath = path
view.addSubview(pView)
//打印调试/引用的边界和路径数据
print (path:,path.bounds)
print()
print(path)$ b $ print()
}
}
让vc = TestViewController()
PlaygroundPage.current.liveView = vc
需要大量的错误检查/处理,但这可能为您找到并使用实际字符字形的边界(而不是标签帧)开了个好头。
结果:
Suppose I have a clock app, and I want to label the hours with characters that could be in an arbitrary character set/font. I'd like to frame the character in a frame and fill it as much as possible. How can I do that? If I use a UILabel
, space gets inserted around the glyph. Here are examples showing two labels, both with the same font but with different characters. The Hebrew numerals all seem shorter than the Arabic numerals. Is there a way to determine the size of the glyphs or somehow push the glyphs out to fit the frame?
As you can see, the Hebrew numeral is shorter even though it's being added to a taller UILabel.
Edit: Since posting, I made a first pass of using core text to see if that could resolve my problem. It seems that it will not. See these illustrations comparing a Hebrew glyph to an Arabic numeral glyph. They yellow is the label bounds. The green is the glyph rectangle reported by core text. I was hoping to get a rectangle flush to the glyph, but it looks like the Hebrew glyphs include space above and beside what I expected to be the glyph. Is there something else I should be checking?
I don't know if you use Obj-C or Swift, but you can paste this into a Swift Playground page to see the result:
Minor Edits
import UIKit
import CoreText
import PlaygroundSupport
class PathView: UIView {
var myPath: UIBezierPath?
override func draw(_ rect: CGRect) {
if let pth = myPath {
UIColor.red.setStroke()
// glyph path is inverted, so flip vertically
let flipY = CGAffineTransform(scaleX: 1, y: -1.0)
// glyph path may be offset on the x coord, and by the height (because it's flipped)
let translate = CGAffineTransform(translationX: -pth.bounds.origin.x, y: pth.bounds.size.height + pth.bounds.origin.y)
// apply the transforms
pth.apply(flipY)
pth.apply(translate)
// stroke the path
pth.stroke()
// print the modified path for debug / reference
print(pth)
}
}
}
class TestViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// blue background so we can see framing
view.backgroundColor = UIColor(red: 0.25, green: 0.5, blue: 01.0, alpha: 1.0)
// use a large font so we can see it easily
let font = UIFont(name: "Times", size: 160)!
// Hebrew character for 8
var unichars = [UniChar]("ח".utf16)
unichars = [UniChar]("י".utf16)
// init glyphs array
var glyphs = [CGGlyph](repeatElement(0, count: unichars.count))
let gotGlyphs = CTFontGetGlyphsForCharacters(font, &unichars, &glyphs, unichars.count)
if gotGlyphs {
// get the cgPath for the character
let cgpath = CTFontCreatePathForGlyph(font, glyphs[0], nil)!
// convert it to a UIBezierPath
let path = UIBezierPath(cgPath: cgpath)
var r = path.bounds
// let's show it at 40,40
r = r.offsetBy(dx: 40.0, dy: 40.0)
let pView = PathView(frame: r)
pView.backgroundColor = .white
pView.myPath = path
view.addSubview(pView)
// print bounds and path data for debug / reference
print("bounds of path:", path.bounds)
print()
print(path)
print()
}
}
}
let vc = TestViewController()
PlaygroundPage.current.liveView = vc
Lots of error checking / handling needed, but this may give you a good start on finding and using the bounds of the actual character glyphs (instead of the label frames).
Result:
这篇关于如何管理文本字形边界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!