开发者

The maximum digit width on different font and font size

开发者 https://www.devze.com 2023-03-22 02:15 出处:网络
I need to get the maximum width of 1,2,3,....8,9 on different font and font size. In c#, the open source code is:

I need to get the maximum width of 1,2,3,....8,9 on different font and font size.

In c#, the open source code is:

    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;

    }

I implemented it in Java. But the results are different.

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;

}

But the result is different betweent c# and java.(I run them on the same machine.)

  1. the result of 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. the result of 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
    


The difference between .NET and Java is due to different assumptions about the screen resolution. .NET works with 96dpi, Java with 72dpi. That is if you ask Java for a 12pt font it will have a different size on the screen than if you ask .NET for the same font. On paper, they will be the same.

If you convert your results to mm (or inch), you'll find that they are the same except for the lost precision due to rounding.

I've also verified the numbers by printing some rows of digits from Microsoft Word and measuring them. Such a reality check often helps.

You're way of measuring the text length in .NET is pretty funny. Why not do it like this:

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();
        }
    }
}


Well, I'd say the problem is you're using different approaches. In Java you just use the FontMetrics of a label that is not even displayed/layed out whereas in C# it seems you're using the size of the label that may have be resized and contain padding, borders etc.

Additionally, in your Java code you truncate dblSizePt to an integer, losing any possibly fraction part. In C# you directly pass fSizePt the the Font construtctor.

Last but not least you're using two different UI frameworks that might have slight differences in text rendering.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号