我是否在“核心文字"中缺少某些内容,可以让我看到某个点在哪一行以及包括段落样式在内的一行到底有多高? [英] Am I missing something in Core Text that will let me see which line a certain point is in and how tall a line really is including paragraph styles?

查看:128
本文介绍了我是否在“核心文字"中缺少某些内容,可以让我看到某个点在哪一行以及包括段落样式在内的一行到底有多高?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图编写一个带有文本的自定义NSView,但不使用NSTextView(因为它不只是文本).我可以使用Core Text绘制文本,但是现在我还需要能够进行插入符和选择矩形的命中测试和绘制.

So I am trying to write a custom NSView with text in it but not using NSTextView (since it will be more than just text). I can use Core Text to draw text, but now I also need to be able to do hit-testing and drawing of the caret and selection rects.

如各种Apple样本所示,天真地绘制插入符号和选择内容的方法是获取包含所需字符串范围的各种CTLine的印刷界线(由于CTLineGetBoundsWithOptions(0)而不是CTLineGetTypographicBounds(),这是由于后者)并填充生成的rect.不幸的是,一旦出现任何类型的段落样式(无论是段落间距,行间距还是行高),这都会停止工作,因为包含段落样式.如果您选择跨多行的文本,则会在行之间看到一些标志性的白色间隙!如果我单击行之间的空白,这仍然无法回答如何知道要使用哪行的问题.

The naive way of drawing carets and selections, as shown by various Apple samples, is to get the typographic bounds of the various CTLines encompassing the desired string range (using CTLineGetBoundsWithOptions(0) instead of CTLineGetTypographicBounds() due to various errors in the latter) and filling the resultant rects. Unfortunately, as soon as there is a paragraph style of any sort (be it paragraph spacing, line spacing, or line height) this stops working because paragraph styles are not included in the typographic bounds. If you select text that spans multiple lines, you'll see that somewhat iconic white gap between the lines! And this still does not answer the question of how to know what line to use if I am clicking on the whitespace between lines.

在克服印刷边界之后,由于核心文本默认情况下如何将度量值捕捉到整数而导致重叠或之间存在间隙,我注意到如果调用CTFrameGetLineOrigins(),则可以通过计算来确定行i + 1的高度origins[i].y - origins[i + 1].y;线0的高度是框架的高度减去其他组合线的高度.在这里使用i + 1很重要;它可以处理由空格高度不同于其他字符高度的字体引起的奇怪情况.

After fighting over typographic bounds rects overlapping or having gaps between them due to how Core Text does snapping metrics points to integers by default, I noticed that if I call CTFrameGetLineOrigins() I can determine the height of line i + 1 by computing origins[i].y - origins[i + 1].y; the height of line 0 is the height of the frame minus the height of the combined other lines. The use of i + 1 here is important; it deals with odd scenarios caused by fonts that have the space height different from other character heights.

但是,使用这种技术,无论该空间是段落空间还是行空间,我都无法区分行上方的间距和行下方的间距.所有间距都被视为在线的上方,如果使用了多个间距模式,则它们会合并在一起.我有一个小程序,您可以使用该程序自己进行试验;单击基线差异"复选框以在行高处加阴影.

However, with this technique, I cannot differentiate between spacing above a line and spacing below a line, whether that space is paragraph or line space. All spacing is treated as being above the line, and if multiple spacing modes are used, they just combine. I have a small program that you can use to experiment with this for yourself; click the "Baseline Diffs" checkbox to shade in line heights.

所以问题是:我想念的是什么,我无法弄清一条线到底有多高,以及其基线相对于其高度在哪里,而不管段落的样式如何?还是我想自己重新实现Core Text的内部逻辑?我确实在一起有很多东西,但是很多都是有条件的……

So the question is: what am I missing that I can't figure out how tall a line really is and where its baseline is relative to its height, regardless of the paragraph style? Or do I need to reimplement the internal logic of Core Text myself if I want to do this? I do have a lot of the pieces together, but a lot of it is highly conditional...

最后一段会发生什么?我应该在那里模拟尾随空间吗?

And what happens on the last paragraph? Should I simulate the trailing space there?

该解决方案需要在OS X 10.8或更高版本上运行.

The solution needs to run on OS X 10.8 or newer.

谢谢.

推荐答案

您需要问自己的一个大问题是,您想要这些事情的结果是什么.线的高度实际上只是线的高度.它不包括线之间的间距.排字机不必使所有行都堆叠在一起.考虑两列布局情况,其中一行可能比上一行.或者,如果有分页符;您认为页面的边距是行高的一部分吗?核心文本不仅仅处理类似于TextView的事物".它可以处理非常任意的布局情况.

The big question you need to ask yourself is what you want the results of these things to be. The hight of the line really is just the hight of the line. It doesn't include the spacing between the lines. The typesetter doesn't have to make all the lines stack. Consider two-column layout situations where a line may be higher than the prior line. Or if there are page breaks; do you consider the page's margins to be part of the line-height? Core Text doesn't just handle "TextView-like things." It handles quite arbitrary layouts situations.

您自己遇到了一个难题:线之间的空间应该属于哪条线.这是您要回答的问题.核心文字不知道您想要什么.它不知道任何这些矩形的含义,也不知道它们是如何协同工作的.

You're running into the hard question yourself of what line the space between the lines should belong to. That's a question for you to answer. Core Text doesn't know what you want. It doesn't know the meaning of any of these rectangles or how you mean them to work together.

因此对于选择问题,是的,您需要通过创建所有完全选中的线矩形的并集(加上第一行和最后一行的额外位)来计算完整框.这就是简单的单列文本通常的处理方式.如果文本可以跨越多列,显然会变得更加复杂.您可能还需要考虑文本向后"流动的情况(即,通常是从左到右的文本,从右到左).

So for the selection question, yes, you'd need to compute the full box by creating a union of all the line rectangles that are fully selected (plus the extra bits on the first and last line). That's how it's usually done for simple, single-column text; obviously it gets a bit more complicated if text can span multiple columns. You may also have to consider situations where text flows "backwards" (i.e. right-to-left inside generally left-to-right text).

仅使用低级Core Text原语需要做很多工作.我将首先尝试使用NSLayoutManager代替,看看它是否足够强大以达到您的目的.如果您的问题只是需要环绕(或跳过)图形或其他非文本元素,则NSLayoutManager可能能够为您完成很多的工作,并让您仍使用NSTextView. NSLayoutManager具有很高的子类别可自定义其行为,并且使用它通常可以保留Cocoa的内置选择功能,而无需重新实现它们.

It's a lot of work using only low-level Core Text primitives. I would first try to use NSLayoutManager instead and see if it's powerful enough for your purposes. If your problem is just that you need to wrap around (or skip over) graphics or other non-text elements, then NSLayoutManager may be able to do a lot of the work for you and let you still use a NSTextView. NSLayoutManager is highly subclassable to customize its behavior, and using it you can often keep Cocoa's built-in selection capabilities without reimplementing them.

这篇关于我是否在“核心文字"中缺少某些内容,可以让我看到某个点在哪一行以及包括段落样式在内的一行到底有多高?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆