不同字体和字体大小的最大数字宽度

时间:2011-07-21 07:37:53

标签: java fonts width

我需要在不同的字体和字体大小上获得最大宽度1,2,3,.... 8,9。

在c#中,开源代码是:

    protected double MaxDigitWidth(string fontName, double dblSizePt)
    {
        double dblMaxDigitWidth = 0.0;

        // Excel does not use the specified font size, 
        // instead, font size is rounded to an integral pixel size
        // check if this works on non-Windows platforms, otherwise 96dpi could do fine here
      //  Graphics g = System.Drawing.Graphics.FromHwnd(new IntPtr());
        float fSizePxl = (float)Math.Round(96 * dblSizePt / 72);
        float fSizePt = (72 * fSizePxl / 96);
        FontStyle fontStyle;
        if (fontName == "Monotype Corsiva")
            fontStyle = FontStyle.Italic;
        else
            fontStyle = FontStyle.Regular;

        Font font = new Font(fontName, fSizePt, fontStyle, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        for (int i = 0; i < 10; i++)
        {
            // use a Label on a .NET 2.0 Form to measure the width of a digit
            Form f = new Form();
            Label l = new Label();
            l.UseCompatibleTextRendering = false;
            l.Font = font;
            l.AutoSize = true;
            f.Controls.Add(l);
            l.Text = Convert.ToString(i) + Convert.ToString(i);
            f.ResumeLayout(false);
            f.PerformLayout();
            int iWidth2 = l.Width;

            l.Text = Convert.ToString(i);
            f.PerformLayout();

            // we measure twice so we can remove the padding
            int iWidth1 = l.Width;

            if (iWidth2 - iWidth1 > dblMaxDigitWidth)
            {
                dblMaxDigitWidth = iWidth2 - iWidth1;
            }
        }
        return dblMaxDigitWidth;

    }

我用Java实现了它。但结果却不同。

protected double MaxDigitWidth(String fontName, double dblSizePt)
{
    double dblMaxDigitWidth = 0.0;
    Font f;
    if (fontName == "Monotype Corsiva")
        f = new Font(fontName, Font.ITALIC ,(int)dblSizePt);
    else
        f = new Font(fontName, Font.PLAIN ,(int)dblSizePt);
    JComponent t = new JLabel();
    FontMetrics fm = t.getFontMetrics(f);
    for (int i = 0; i < 10; i++)
    {       
     int iWidth2 = fm.stringWidth(String.valueOf(i)+String.valueOf(i));
     int iWidth1 = fm.stringWidth(String.valueOf(i));

     if (iWidth2 - iWidth1 > dblMaxDigitWidth)
     {
         dblMaxDigitWidth = iWidth2 - iWidth1;
     }
    }
     return dblMaxDigitWidth;

}

但结果在c#和java之间是不同的。(我在同一台机器上运行它们。)

  1. c#

    的结果
          Font and Font size                Maximum digit widht 
        a = MaxDigitWidth("Arial", 11.0);    8
        a = MaxDigitWidth("Arial", 12.0);    9 
        a = MaxDigitWidth("Arial", 13.0);    9 
        a = MaxDigitWidth("Arial", 14.0);    11 
        a = MaxDigitWidth("Arial", 15.0);    11 
        a = MaxDigitWidth("Arial", 16.0);    12 
        a = MaxDigitWidth("Arial", 17.0);    13 
        a = MaxDigitWidth("Arial", 18.0);    13   
        a = MaxDigitWidth("Arial", 19.0);    14   
        a = MaxDigitWidth("Arial", 20.0);    15   
    
  2. java的结果

        Arial-11           6.0
        Arial-12           7.0
        Arial-13           7.0
        Arial-14           8.0
        Arial-15           8.0
        Arial-16           9.0
        Arial-17           9.0
        Arial-18           10.0
        Arial-19           11.0
        Arial-20           11.0
    

2 个答案:

答案 0 :(得分:3)

.NET和Java之间的区别是由于对屏幕分辨率的不同假设。 .NET适用于96dpi,Java适用于72dpi。也就是说,如果你向Java询问12pt字体,它在屏幕上的大小将与你要求.NET使用相同字体的大小不同。在纸面上,它们将是相同的。

如果将结果转换为mm(或英寸),除了由于四舍五入而导致的精度损失之外,您会发现它们是相同的。

我还通过从Microsoft Word打印一些数字并测量它们来验证数字。这种现实检查通常会有所帮助。

你测量.NET中的文本长度非常有趣。为什么不这样做:

using System;
using System.Drawing;

namespace Codo
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap bitmap = new Bitmap(100, 100);
            Graphics graphics = Graphics.FromImage(bitmap);
            graphics.PageUnit = GraphicsUnit.Pixel;
            StringFormat strFormat = new StringFormat(StringFormat.GenericTypographic);
            for (int fontSize = 11; fontSize <= 20; fontSize++)
            {
                Font font = new Font("Arial", fontSize, FontStyle.Regular);
                float digitWidth = graphics.MeasureString("00000000", font, 1000, strFormat).Width / 8;
                font.Dispose();
                Console.WriteLine("Width of digit 0 for {0} {1}pt: {2} (96dpi)", font.FontFamily.Name, font.SizeInPoints, digitWidth);
                digitWidth = digitWidth / 96 * 72;
                Console.WriteLine("Width of digit 0 for {0} {1}pt: {2} (72dpi)", font.FontFamily.Name, font.SizeInPoints, digitWidth);
            }
            graphics.Dispose();
            bitmap.Dispose();
        }
    }
}

答案 1 :(得分:1)

嗯,我说问题是你正在使用不同的方法。在Java中,您只需使用甚至不显示/布局的标签的FontMetrics,而在C#中,您似乎正在使用可能已调整大小并包含填充,边框等标签的大小。

此外,在您的Java代码中,您将dblSizePt截断为整数,丢失任何可能的小数部分。在C#中,您直接通过fSizePt Font construtctor。

最后但并非最不重要的是,您使用的两个不同的UI框架在文本呈现方面可能略有不同。