访问 NSTextView 指标
Accessing NSTextView metrics
我有一个 NSTextVIew
,其中我只显示标准字母表中的等宽字符。所以没有数字、特殊字符、表情符号等。每个字符等于一个字形。在文本之上我需要绘制一些形状,我正在寻找一种从文本系统访问一些指标的方法:
- 一个字符到下一个字符的距离
- 一行到下一行的距离
看图就是我的意思
好像没有我可以直接使用的属性,或者至少我还没有找到,所以我现在使用文本视图的layoutManager
来获取这些值:
对于第一个,我通过布局管理器的 boundingRect(forGlyphRange glyphRange: NSRange, in container: NSTextContainer) -> NSRect
方法获得了两个相邻字符的封闭矩形,并减去两个矩形的 origin.x。
对于第二个,我可以使用相同的函数,但是我需要知道第二行第一个字符的范围。或者遍历所有字符,一旦封闭矩形的 origin.y 发生变化,我在第二行有第一个字符,我可以计算两行之间的距离。
EDIT :这是使用布局管理器的可能代码:
typealias TextMetrics = (distanceBetweenCharacters: CGFloat, distanceBetweenLines: CGFloat)
var metrics: TextMetrics = self.textMetrics() // need to update when text changes
func textMetrics() -> TextMetrics {
guard let lm = self.layoutManager,
let tc = self.textContainer
else { return (0,0)
}
var distanceBetweenCharacters: CGFloat = 0.0
var distanceBetweenLines: CGFloat = 0.0
if string.count > 2 {
let firstRect = lm.boundingRect(forGlyphRange: NSRange(location: 0, length: 1), in: tc)
let secondRect = lm.boundingRect(forGlyphRange: NSRange(location: 1, length: 1), in: tc)
distanceBetweenCharacters = secondRect.maxX - firstRect.maxX
for (index, _) in string.enumerated() {
let rect = lm.boundingRect(forGlyphRange: NSRange(location: index, length: 1), in: tc)
if rect.maxY > firstRect.maxY { // reached next line
distanceBetweenLines = rect.maxY - firstRect.maxY
break
}
}
}
return (distanceBetweenCharacters, distanceBetweenLines)
}
我也看过从 defaultParagraphStyle
获取这些,但如果我访问它,它是 nil
。
是否有另一种更简单的方法来获取这些值?
经过更多的搜索和试错,我发现 distanceBetweenLines
可以从字体规格和 lineHeightMultiple 计算出来,它是 NSParagraphStyle
的 属性,但是它也可以在段落样式之外定义,我就是这样做的。
所以最后这个有效:
let distanceBetweenLines = layoutManager.defaultLineHeight(for: myTextFont) * lineHeightMultiple
对于distanceBetweenCharacters
,我还没有找到其他解决方案。
编辑
根据@Willeke 在下面评论中的建议,我现在计算 distanceBetweenCharacters
如下:
let distanceBetweenCharacters = myTextFont.advancement(forCGGlyph: layoutManager.cgGlyph(at: 0)).width + myKerning
我有一个 NSTextVIew
,其中我只显示标准字母表中的等宽字符。所以没有数字、特殊字符、表情符号等。每个字符等于一个字形。在文本之上我需要绘制一些形状,我正在寻找一种从文本系统访问一些指标的方法:
- 一个字符到下一个字符的距离
- 一行到下一行的距离
看图就是我的意思
好像没有我可以直接使用的属性,或者至少我还没有找到,所以我现在使用文本视图的layoutManager
来获取这些值:
对于第一个,我通过布局管理器的 boundingRect(forGlyphRange glyphRange: NSRange, in container: NSTextContainer) -> NSRect
方法获得了两个相邻字符的封闭矩形,并减去两个矩形的 origin.x。
对于第二个,我可以使用相同的函数,但是我需要知道第二行第一个字符的范围。或者遍历所有字符,一旦封闭矩形的 origin.y 发生变化,我在第二行有第一个字符,我可以计算两行之间的距离。
EDIT :这是使用布局管理器的可能代码:
typealias TextMetrics = (distanceBetweenCharacters: CGFloat, distanceBetweenLines: CGFloat)
var metrics: TextMetrics = self.textMetrics() // need to update when text changes
func textMetrics() -> TextMetrics {
guard let lm = self.layoutManager,
let tc = self.textContainer
else { return (0,0)
}
var distanceBetweenCharacters: CGFloat = 0.0
var distanceBetweenLines: CGFloat = 0.0
if string.count > 2 {
let firstRect = lm.boundingRect(forGlyphRange: NSRange(location: 0, length: 1), in: tc)
let secondRect = lm.boundingRect(forGlyphRange: NSRange(location: 1, length: 1), in: tc)
distanceBetweenCharacters = secondRect.maxX - firstRect.maxX
for (index, _) in string.enumerated() {
let rect = lm.boundingRect(forGlyphRange: NSRange(location: index, length: 1), in: tc)
if rect.maxY > firstRect.maxY { // reached next line
distanceBetweenLines = rect.maxY - firstRect.maxY
break
}
}
}
return (distanceBetweenCharacters, distanceBetweenLines)
}
我也看过从 defaultParagraphStyle
获取这些,但如果我访问它,它是 nil
。
是否有另一种更简单的方法来获取这些值?
经过更多的搜索和试错,我发现 distanceBetweenLines
可以从字体规格和 lineHeightMultiple 计算出来,它是 NSParagraphStyle
的 属性,但是它也可以在段落样式之外定义,我就是这样做的。
所以最后这个有效:
let distanceBetweenLines = layoutManager.defaultLineHeight(for: myTextFont) * lineHeightMultiple
对于distanceBetweenCharacters
,我还没有找到其他解决方案。
编辑
根据@Willeke 在下面评论中的建议,我现在计算 distanceBetweenCharacters
如下:
let distanceBetweenCharacters = myTextFont.advancement(forCGGlyph: layoutManager.cgGlyph(at: 0)).width + myKerning