如何实现文本选择?

发布于 2024-10-10 08:40:17 字数 425 浏览 3 评论 0原文

我的问题不是基于语言或基于操作系统的。我想每个系统都提供某种 TextOut(text, x, y) 方法。我正在寻找一些指南或文章,我应该如何实现输出文本的选择。找不到任何有关此的信息。

我想到的唯一一件事是这样的:

当用户单击文本画布上的某个点时,我知道该点的坐标。我需要计算它在文本缓冲区中的确切位置。因此,我从缓冲区的开头进行遍历,并对每个字符(或文本块)应用一种样式(如果有的话)。之后,我知道在给定样式后,字母就有了给定的大小。我将其宽度和高度添加到之前计算的 X、Y 坐标中。这样,我就遍历缓冲区,直到计算出的位置还没有到达用户已经点击的点。当我到达某个偏移范围内的点后,我就有了选择的起点。

这是基本思想。我不知道这是否好,我想知道这是如何真正做到的,例如在 Firefox 中。我知道我可以浏览资源,如果我别无选择,我会这样做。但首先我想找到一些关于它的文章......

My question is not language based or OS based. I guess every system is offering some sort of TextOut(text, x, y) method. I am looking for some guidlines or articles how should I implement selection of outputed text. Could not find any info about this.

The only thing which comes to my mind is like this:

When user clicks some point on the text canvas I know the coordinates of this point. I need to calculate where exactly it will be in my text buffer. So I am traversing from the begining of the buffer and I am applying to each character (or block of text) a style (if it has any). After this, I know that after given style the letter has given size. I am adding its width and height to previously calculated X,Y coordinates. In this way, I am traversing the buffer until the calculated position has not reached the point that has been clicked by the user. After I reach the point within range of some offset I have starting point for the selection.

This is the basic idea. I don't know if this is good, I would like to know how this is done for real like for example in Firefox. I know I could browse the sources and if I won't have a choice I'll do it. But first I am trying to find some article about it...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瑕疵 2024-10-17 08:40:18

选择文本本质上是特定于包含该文本的控件及其存储该文本的方式的。

一种非常简单(尽管效率低下的方法)是在单击某个点时运行您正在使用的文本流算法,并在到达最接近该点时停止该算法。更高级的控件可能会缓存文本布局,以便更有效地进行选择或绘制其内容。根据您对 CPU 时间或内存的重视程度,可以使用缓存和特殊情况来降低“命中测试”的成本。

如果您可以做出任何断言(控件中只有一种字体,因此每行都具有相同的高度),那么可以通过按行索引字体布局,然后进行简单的算术来找出单击了哪一行,从而使这些测试更便宜在。如果您的文本控件也使用等宽字体(每个字符占用相同的宽度和高度),那么您会更幸运,因为您可以通过查找表和两个简单​​的除法直接跳转到字符信息。

请记住,从头开始编写文本控件极其困难。为了获得最佳实践,您应该将文档内容与显示信息分开。这样做的原因是因为文本本身需要经常编辑,因此可以在数据侧采用诸如 Ropes 或 Gap Buffers 之类的算法,以在插入符周围提供更快的插入速度。每次编辑文本时,也必须对其进行渲染,这涉及获取该数据并通过某种格式/流算法运行它,以确定需要如何向用户显示它。 这两方面都需要大量算法,而这些算法可能会很烦人。

不幸的是,使用本机 TextOut 函数对您没有帮助。您将需要使用为您提供单个字符的文本范围的方法,并且更高级(例如多行)控件通常必须使用此信息自行呈现字符。像 TextOut 这样的函数并不是为了处理闪烁的插入符号或对文本布局执行增量更新而构建的。虽然某些 TextOut 样式函数可能支持自动换行和对齐,但它们还需要重新呈现整个字符串,这与您需要在控件中处理的文本量成正比,这变得更加不可取。

Selecting text is inherently specific to the control which is containing it and the means it stores that text.

A very simple (though questionably inefficient means) is to run the text flow algorithm you are using when clicking on a point and stopping the algorithm when you have reached what is closest to that point. More advanced controls might cache the text layout to make selections or drawing their content more efficient. Depending on how much you value CPU time or memory there are ways to use caches and special cases to make this “hit test” cheaper.

If you can make any assertions (only one font in the control, so every line has the same height) then it is possible to make these tests cheaper by indexing the font layout by lines and then doing simple arithmetic to find out which line was clicked on. If your text control is also using monospace fonts (every character occupies the same width as well as height) then you are in even more luck, as you can jump straight to the character information via a lookup table and two simple divisions.

Keep in mind that writing a text control from scratch is obscenely difficult. For best practice, you should keep the content of the document separate from the display information. The reason for this is because the text itself will need to be edited quite often, so algorithms such as Ropes or Gap Buffers may be employed on the data side to provide faster insertion around the caret. Every time text is edited it must also be rendered, which involves taking that data and running it through some kind of formatting / flow algorithms to determine how it needs to be displayed to the user. Both of these sides require a lot of algorithms that may be annoying to get right.

Unfortunately using the native TextOut functions will not help you. You will need to use methods which give you the text extents for individual characters, and more advanced (multiline for example) controls often must do their own rendering of characters using this information. Functions like TextOut are not built to deal with blinking insertion carets for example, or performing incremental updates on text layouts. While some TextOut style functions may support word wrap and alignment for you, they also require re-rendering the entire string which becomes more undesirable in proportion to the amount of text you need to work with in your control.

夏末 2024-10-17 08:40:18

你的思考水平比必要的低得多(不是侮辱。你认为你需要做比你需要做的更多的工作)。大多数(如果不是全部)具有 GUI 支持的语言也会有某种形式的选择范围,它为您提供所选的字符串或字符串中的开始和结束索引。

使用现代语言,您永远不必计算像素和字符宽度。

有关 Javascript 中的文本选择,请参阅此问题:了解使用 JavaScript 选择文本区域会发生什么

You are thinking at a much lower level than necessary (not an insult. you are thinking that you need to do much more work then you need to). Most (if not all) languages with GUI support will also have some form of selectionRange that gives you either the string that was selected or the start and stop indices in the string.

With a modern language, you should never have to calculate pixels and character widths.

For text selection in Javascript, see this question: Understanding what goes on with textarea selection with JavaScript

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文