使用可变宽度字体时,文本编辑器如何计算光标位置?
How do text editors calculate cursor position when using a variable width font?
我找不到关于该主题的任何信息。是否有通用算法,或者它是否因编辑器而异?
提前致谢
我假设您想将 [pixels]
中的鼠标位置转换为 [char]
中的光标位置,然后返回。
渲染 API 通常提供以像素为单位返回文本宽度和高度的函数,而不是渲染它。这可以用来在字符和像素位置之间进行转换。
(cx,cy) [char] -> (mx,my) [pixels]
可以像这样直接完成(VCL):
mx = TextWidth(Substring(line[cy],1,cx))
my = FontHeight*cy
其中 line[]
包含编辑器的行。 TextWidth
与渲染文本的特定视觉对象 Canvas 紧密相关,因此它应该是 object->Canvas->TextWidth(...
并且 FontHeight
应该是编辑器的行高(以像素为单位)。
逆向转换(mx,my) [pixels] -> (cx,cy) [char]
比较棘手。 cy
坐标是简单的除法,但是 cx
必须迭代。对于普通文本 windows 是简单的线性 O(n)
搜索就足够了(获取以像素为单位的字符串宽度,因此先测试单个字符,然后测试第 2 个字符,然后第 3 个 ... 直到 x >= mx
)。
然而,一旦行太长,您可以使用二进制搜索来加快速度。另一种选择是使用平均字符宽度将鼠标位置除以它以获得大致的字符位置,然后简单地从该位置线性搜索。
请注意,一旦您开始使用 Unicode 编码(如 UTF-8)和/或 esc 代码(如制表符),您需要记住平均字符宽度并不总是一个好的方法。
这里是线性搜索的例子:
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,则需要在您的环境中找到对应的 TextWidth
。 Substring
也是如此。当心代码示例未在答案编辑器中直接测试和编写,因此可能存在错误(如语法错误)
无论如何,现代编程环境都有可供使用的编辑器组件(如 VCL 中的 TMemo
),其中已经实现了所有这些功能。
我找不到关于该主题的任何信息。是否有通用算法,或者它是否因编辑器而异?
提前致谢
我假设您想将 [pixels]
中的鼠标位置转换为 [char]
中的光标位置,然后返回。
渲染 API 通常提供以像素为单位返回文本宽度和高度的函数,而不是渲染它。这可以用来在字符和像素位置之间进行转换。
(cx,cy) [char] -> (mx,my) [pixels]
可以像这样直接完成(VCL):
mx = TextWidth(Substring(line[cy],1,cx))
my = FontHeight*cy
其中 line[]
包含编辑器的行。 TextWidth
与渲染文本的特定视觉对象 Canvas 紧密相关,因此它应该是 object->Canvas->TextWidth(...
并且 FontHeight
应该是编辑器的行高(以像素为单位)。
逆向转换(mx,my) [pixels] -> (cx,cy) [char]
比较棘手。 cy
坐标是简单的除法,但是 cx
必须迭代。对于普通文本 windows 是简单的线性 O(n)
搜索就足够了(获取以像素为单位的字符串宽度,因此先测试单个字符,然后测试第 2 个字符,然后第 3 个 ... 直到 x >= mx
)。
然而,一旦行太长,您可以使用二进制搜索来加快速度。另一种选择是使用平均字符宽度将鼠标位置除以它以获得大致的字符位置,然后简单地从该位置线性搜索。
请注意,一旦您开始使用 Unicode 编码(如 UTF-8)和/或 esc 代码(如制表符),您需要记住平均字符宽度并不总是一个好的方法。
这里是线性搜索的例子:
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,则需要在您的环境中找到对应的 TextWidth
。 Substring
也是如此。当心代码示例未在答案编辑器中直接测试和编写,因此可能存在错误(如语法错误)
无论如何,现代编程环境都有可供使用的编辑器组件(如 VCL 中的 TMemo
),其中已经实现了所有这些功能。