基于内容的文本宽度估算算法

这是一个很长的镜头,但是有没有人知道根据其内容估算和分类文本宽度(对于可变宽度字体)的算法?

例如,我想知道iiiiiiii不像abcdefgh那么宽,而abcdefgh又不像WWWWWWWW那么宽,即使所有三个字符串的长度都是8个字符。

这实际上是尝试将一些智能构建到字符串截断方法中,该方法目前正在截断视觉上宽的字符串,但也不必要地截断视觉上狭窄的字符串,因为两个字符串包含相同数量的字符。 算法可能足以将输入字符串分类为正常 ,然后根据需要进行截断。

这个问题并不是特定于语言,但如果有算法,那么我将用Java实现它。 这适用于Web应用程序。 我知道SO上有答案可以解决这个问题,使用JavaScript来获取包含div元素的宽度,但我想知道服务器端解决方案是否可行。

大多数GUI框架提供了一些计算给定输出设备上字体的文本度量的方法。

例如,使用java.awt.FontMetrics ,我相信你可以这样做:

 import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; public int measureText(Graphics g, String text) { g.setFont(new Font("TimesRoman", Font.PLAIN, 12)); FontMetrics metrics = g.getFontMetrics(); return metrics.stringWidth(text); } 

没有经过测试,但你明白了。


在.Net下,您可以使用Graphics.MeasureString方法。 在C#中:

 private void MeasureStringMin(PaintEventArgs e) { // Set up string. string measureString = "Measure String"; Font stringFont = new Font("Arial", 16); // Measure string. SizeF stringSize = new SizeF(); stringSize = e.Graphics.MeasureString(measureString, stringFont); // Draw rectangle representing size of string. e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height); // Draw string to screen. e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0)); } 

这对我有用:

 AffineTransform af = new AffineTransform(); FontRenderContext fr = new FontRenderContext(af,true,true); Font f = new Font("Arial", 0, 10); // use exact font double width= f.getStringBounds("my string", fr).getWidth(); 

对于Web应用程序,您无法(真正)获得正确的估计。 不同的字体具有不同的宽度,因此这不仅取决于客户端(浏览器)及其缩放和DPI设置,还取决于该计算机(和操作系统)上存在的字体或其替换。

如果您需要精确测量,请创建一个图形(位图,SVG,甚至某些PDF或其他),这些图形将在服务器上而不是客户端上进行布局和渲染。

没有可靠的服务器端解决方案来计算文本宽度。 (在创建文本图像之外,可能是SVG)

如果您尝试使用像浏览器一样的工具并在相对基本的页面上运行它,您将立即看到原因。 很难预测即使最平凡的例子会变得多么广泛,更不用说如果用户决定放大浏览器等……

没有准确地说你可能想要截断字符串(它可能有助于提供潜在的解决方案),但常见的是因为你想在某个点切断文本并提供一个椭圆。

这可以通过使用css属性在许多浏览器平台上可靠地完成,并且没有 javascript:

http://www.jide.fr/emulate-text-overflowellipsis-in-firefox-with-css

您真的无法知道客户端使用的浏览器,字体设置,屏幕大小等。 (好的,有时请求标头提供指示,但实际上没有任何一致性或可靠性。)

所以,我会:

  • 在Internet Explorer中显示一些示例文本,默认设置为1024×768的屏幕/窗口大小(这通常是最常见的大小)
  • 使用此配置获取平均字符/行,并将其用于估算。

我通常发现这个“足够好”,例如,用于估计某些文本将在浏览器上占用的行数,以便估计文本旁边显示的广告数量。

如果它对你真的非常重要,那么我可以想象一个复杂的方案,你最初向客户端发送一些Javascript,然后进行测量并将其发送回你的服务器,然后你将这些信息用于以后的页面。客户。 但我无法想象它通常值得付出努力。

我认为您应该选择以下解决方案之一:

  • 精确解决方案:总结字符串中每个字符的宽度(大多数API将为您提供此信息)
  • 快速估算:取最大或最小宽度,然后乘以字符数。

当然可能会有一些混合估计,但我认为这是在错误的方向上付出太多努力。

对于一个不错的*客户端解决方案,您可以尝试使用RichieHindle对我的问题的回答建议的混合CSS和Javascript方法。

鉴于您不知道用户将看到该页面的字体(它们总是可以覆盖您的选择,Ctrl- +页面等),在浏览器上执行此操作的“正确”位置…虽然浏览器不要轻松!

*当我说“好”时,我的意思是“可能很好,但我还没有尝试过”。

这实际上是尝试将一些智能构建成字符串截断方法[…]

真的值得努力吗? 我们遇到了这个问题。 这是跨语言的。 解决方法是保持原样。 保持这种智能的复杂性随着您添加支持的每种语言而迅速(并且可能呈指数级)增加。 因此我们的决定。

[…]一种基于其内容估算和分类文本宽度(对于可变宽度字体)的算法?

大多数字体库都会为您提供此信息。 但这是相当低级的东西。 基本思想是传入一个字符串并以磅为单位返回宽度。