无法对齐NSLayoutManager的基线

时间:2017-02-07 20:41:10

标签: ios uiview textkit nslayoutmanager nstextcontainer

我正在开发一个自定义UIView,它使用多个单独的NSLayoutManager对象呈现文本。 (此视图具有超出内置文本视图类可支持的文本定位要求。)当布局文本为希伯来语时,我很难获得其中一个布局的正确垂直位置。我为这篇文章的篇幅道歉,但我希望尽可能多地包含相关细节。

问题

这是我想要完成的一个例子:

enter image description here

“2”的基线与希伯来字母“ו”(以自定义字体呈现)的基线很好地对齐。但是,如果我将“2”的文本切换为希伯来语数字(实际上是希伯来语字母“ב”,其在数字上下文中的值为2),它就像这样(“ב”太高):

enter image description here

此处更改为文本字符串。而不是"2",而是"\u{05b1}"。我希望所有内容都在一个共同的基线上,并希望有任何解决问题的建议(所有希伯来语数字都会发生,而不仅仅是"\u{05b1}")。

代码

(我应该提一下,由于技术原因,我不能对数字和主要文本使用单个NSLayoutManager。)我试图通过垂直移动渲染位置来对齐基线数字乘以字体上升的差异。这是计算班次的代码:

numberFont = UIFont.systemFont(ofSize: /* some size */)
offset = fullFont.ascender - numberFont.ascender

以下是我为数字创建NSLayoutManager的方法:

var lbl = "2" // or "\u{05b1}"

let paraStyle = NSMutableParagraphStyle()
paraStyle.alignment = .center
let text = NSTextStorage(
    string: lbl,
    attributes: [NSFontAttributeName: numberFont,
                 NSParagraphStyleAttributeName: paraStyle]
)

let layout = NSLayoutManager()
text.addLayoutManager(layout)
let container = NSTextContainer(
    size: CGSize(width: /* some fixed width */, height: bounds.height - offset)
)
container.lineFragmentPadding = 0
layout.addTextContainer(container)

let x = ... // irrelevant
let origin = CGPoint(x: x, y: bounds.minY + offset)

稍后,我使用以下方式呈现文本:

let range = layout.glyphRange(for: layout.textContainers[0])
layout.drawGlyphs(forGlyphRange: range, at: origin)

主要文本使用相同的逻辑处理,但没有offset(当然也有不同的字体)。这适用于阿拉伯数字(例如“2”),但希伯来语数字(例如“ב”)则失败。

更多信息

对于上面的图片,字体大小(.pointSize)和上升(.ascender)属性为:

  

个尺寸:text = 14.3890409469604;数字= 8.63342465753425
  上升:text = 16.159567469731; number = 8.2203017979452

我还生成了一些关于布局的诊断信息,但这些数字对我来说并没有多大意义。这是打印信息的代码:

size = text.size()
mgr = NSLayoutManager()
text.addLayoutManager(mgr)
container = NSTextContainer(
    size: CGSize( width: CGFloat.greatestFiniteMagnitude,
                 height: CGFloat.greatestFiniteMagnitude))
container.lineFragmentPadding = 0
mgr.addTextContainer(container)
mgr.ensureLayout(for: container)
range = mgr.glyphRange(for: container)

print("label:", lbl)
print("  text size:", size)
print("     bounds:", mgr.boundingRect(forGlyphRange: range, in: container))

以下是两个文本(“2”和“\ u {05d1}”)的结果:

  

标签:2
    文字大小:(5.3958904109589,10.3027782534247)
    界限:(0.0,0.0,5.3958904109589,10.3027782534247)
   label:ב
   文字大小:(4.67931616438356,9.99459726027397)
   界限:(-1.88208657534247,-0.578439452054793,9.5054005479452,9.77303671232876)

关于这个难题的几件事我:

  • 希伯来语文本的边界从x和y的负值开始。负x的起源可能与希伯来语是一个从右到左的脚本有关,但负面y起源呢?
  • 报告的布局大小是边界高度和边界的y起点或容器中文本底部(可能更精确地)的代数和,而不是实际的整体大小。 NSAttributedString.size()被打破了吗?
  • 这些数字似乎都没有解释“2”和“\ u {05d1}”垂直位置的视觉差异。

0 个答案:

没有答案