文本编辑器在使用可变宽度字体时如何计算光标位置?



我找不到关于这个主题的任何信息。是否有一个共同的算法,或者它是不同的编辑器?

Thanks in advance

我假设您想将鼠标在[pixels]中的位置转换为光标在[char]中的位置,并返回。

渲染API通常提供以像素为单位返回文本宽度和高度的函数,而不是渲染它。这可以用于字符和像素位置之间的转换。

(cx,cy) [char] -> (mx,my) [pixels]可以直接完成,例如(VCL):

mx = TextWidth(Substring(line[cy],1,cx))
my = FontHeight*cy

其中line[]保存编辑器的行。TextWidth与渲染文本的特定视觉对象画布紧密相关,因此object->Canvas->TextWidth(...FontHeight应该是编辑器的行高(以像素为单位)。

反向转换(mx,my) [pixels] -> (cx,cy) [char]更棘手。cy坐标是简单的除法,但cx必须迭代。对于普通文本窗口是简单的线性O(n)搜索足够(以像素为单位获得字符串宽度,因此测试第一个字符,然后第一个2,然后第一个3…直到x >= mx).

然而,一旦行太长,你可以使用二分搜索来加快速度。另一种选择是使用avg字符宽度将鼠标位置除以它以获得近似字符位置,然后简单地从该位置线性搜索。

注意,一旦你开始使用Unicode编码,如UTF-8和或esc编码,如制表符,你需要记住,avg字符宽度并不总是一个好方法。

线性搜索的例子:

cy = my/FontHeight
for (cx=0;;)
{
if (line[cy].Length()<=cx) break; // end of line reached
if (mx<TextWidth(Substring(line[cy],1,cx))) break;
cx++;
}

如果您不使用VCL,那么您需要在您的环境中找到对应的TextWidthSubstring也是如此。注意代码示例不是直接在回答编辑器中测试和编写的,因此可能会出现错误(如语法和关闭)

无论如何,现代编程环境已经准备好使用编辑器组件(如VCL中的TMemo),它已经实现了所有这些功能。

最新更新