如何计算字体的点大小以最佳适应预定义的区域?

3
我有一个有趣的问题。我已经接近解决它了,但是我很好奇其他人会如何解决这个问题。我想在预定义的区域中显示一些多行文本。我不知道文本内容或区域大小,因此该函数必须被通用编写。您可以假设始终使用标准字体,但点大小必须更改。
假设您有一个函数,该函数将以字符串参数传递要绘制的文本。该函数具有要绘制的表单对象,并且还传递一个矩形对象,该对象定义了表单上文本的边界区域。该函数需要在给定的矩形区域内尽可能大地显示文本。对于我来说,挑战在于计算使用的字体大小,以使文本尽可能适合在矩形中,且具有最小的空白间隙。
以下两个方程可能有用:
float pixels = (points *dpi)/72f;
float points = (pixels*72f)/dpi);

此外:
float dpi = CreateGraphics().DpiY;

哇,看到迄今为止的建议,我没想到最后一部分会如此迭代!如果我们假设文本没有换行,那该怎么办?硬回车将打断多行,因此我们只需要担心最长的一行宽度。 - AlanKley
3个回答

2
很棘手。直接计算点大小是行不通的,文本的宽度取决于字体度量。二分搜索是一种明显的策略,但在实践中无法奏效。TrueType提示和单词换行共同破坏了它。
我建议您从二分搜索开始,将hi和lo设置为合理的默认值,如72和6。然后,当范围缩小到5个点时,开始测试每个单独的点大小,直到找到最大的适合的大小。编写算法时,请确保考虑适合大小N但不适合大小N-1的情况。

不允许自动换行会更容易吗? - AlanKley
是的,二分查找失败的可能性要小得多。但由于提示,不为零。当范围少于1点时停止搜索。 - Hans Passant

2
任何方案都存在一个重要问题,就是你需要根据宽度来确定解决方案,而宽度完全取决于字体。这意味着你需要根据预定义的点大小字体独立计算每个单词的宽度。随着点大小的改变,其一致性不能得到保证。
如果你想让解决方案准确,那么速度就会变慢。
我建议选择两个点大小(比如6和18),分别代表最小和中高点,并计算每个点大小下每个单词的像素宽度。然后可以计算出两种文本的面积。
接着,可以推断出适当的矩形区域的面积,并根据文本长度使用任意宽度/高度比例来确定目标大小(宽度和高度) - 例如,有一个最佳的可读宽度。
然后,你需要迭代地尝试在矩形内进行单词换行,并向后使用点大小,直到文本适合矩形范围内。

如果我们不考虑自动换行会怎样呢?我们假设换行符将分隔每一行,而且没有任何一行会超出矩形框。 - AlanKley
重要的是先计算宽度,一旦计算出来就不要改变它,然后可以使用宽度限制行的长度,最终得到一个可能会多出一两行的矩形。这并不总是看起来很好,但报纸栏目使用精心计算的列宽以实现最大可读性。选择美国信纸或A4比例的矩形(约为1.3:1)。此外,单词宽度数组将有助于快速迭代解决方案。 - Cycles McHurtz

0

点大小的二分搜索: 从最大可用的点大小开始。如果不适合,则尝试其一半,...


你如何确定一个“fit”? - AlanKley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接