计算DXF的文本宽度

时间:2015-07-07 06:26:26

标签: c# text-rendering dxf

我使用netDXF(https://netdxf.codeplex.com/)生成用于AutoCAD的DXF文件。但是,我有一个问题,让MText的宽度正确。我希望能够定义文本应该适合的宽度,并更改文本的宽度因子(水平压扁),使其适合定义的区域。因此,如果我有40毫米的宽度来装入文本并且文本长度为80毫米,则需要宽度系数为0.5。唯一的问题是我不知道如何准确地确定文本的宽度。我尝试了以下方法,但未能成功获得正确的结果:

Why is Graphics.MeasureString() returning a higher than expected number?

Measure a String without using a Graphics object?

http://www.codeproject.com/Articles/2118/Bypass-Graphics-MeasureString-limitations

我附上了我的代码。我基本上使用3种方法中的每一种打印水平线来计算文本宽度并将其与实际文本宽度进行比较。如果我更改字体,我会得到不同的结果。我附上了两张照片。一个使用Calibri的代码和一个使用Arial的代码。无论我使用什么字体,我都需要将该行放在文本的边缘。

Arial

Calibri 这是我的代码:

public void TestMethod1()
        {
            Application.SetCompatibleTextRenderingDefault(false);

            //text width in mm
            float textWidth = 40;
            float textHeight = 200;
            string labelText = "HELLO WORLD!";
            TextStyle textStyle = new TextStyle("Calibri");

            DxfDocument dxf = new DxfDocument();
            Layer layer1 = new Layer("layer1");
            layer1.Color = new AciColor(0, 0, 255);
            layer1.Name = "Text";

            MText text1 = new MText(new Vector2(0, 0), textHeight, 0, textStyle);
            text1.Layer = layer1;
            text1.AttachmentPoint = MTextAttachmentPoint.MiddleCenter;

            //Will the text fit in the bounds of the rectangle? If not change width factor so it does.
            Font f = new Font(textStyle.FontName, textHeight);
            Size size = TextRenderer.MeasureText(labelText, f);
            SizeF sizeF = graphicsMeasureString(labelText, f);
            int width = MeasureDisplayStringWidth(labelText, f);

            float widthFactor = Math.Min(1, textWidth / sizeF.Width);
            MTextFormattingOptions mtextOptions = new MTextFormattingOptions(text1.Style);
            //mtextOptions.WidthFactor = widthFactor;
            text1.Write(labelText, mtextOptions);

            //Red, g.MeasureString
            Line line1 = new Line(new Vector2(0 - sizeF.Width / 2, 0), new Vector2(0 + sizeF.Width / 2, 0));
            line1.Color = new AciColor(255, 0, 0);

            //Green, TextRenderer
            Line line2 = new Line(new Vector2(0 - size.Width / 2, 5), new Vector2(0 + size.Width / 2, 5));
            line2.Color = new AciColor(0, 255, 0);

            //Yellow, MeasureDisplayStringWidth
            Line line3 = new Line(new Vector2(0 - width / 2, -5), new Vector2(0 + width / 2, -5));
            line3.Color = new AciColor(255, 255, 0);

            dxf.AddEntity(text1);
            dxf.AddEntity(line1);
            dxf.AddEntity(line2);
            dxf.AddEntity(line3);
            dxf.Save("Text Width Test.dxf");

        }

        public SizeF graphicsMeasureString(string text, Font f)
        {
            Bitmap fakeImage = new Bitmap(1, 1);
            Graphics g = Graphics.FromImage(fakeImage);
            SizeF sizeF = g.MeasureString(text, f, new PointF(100, 0), StringFormat.GenericTypographic);

            return sizeF;
        }

        public int MeasureDisplayStringWidth(string text, Font f)
        {
            Size size = TextRenderer.MeasureText(text, f);
            Bitmap fakeImage = new Bitmap(1, 1);
            Graphics g = Graphics.FromImage(fakeImage);

            System.Drawing.StringFormat format = new System.Drawing.StringFormat();
            System.Drawing.RectangleF rect = new System.Drawing.RectangleF(0, 0, 1000, 1000);
            System.Drawing.CharacterRange[] ranges = { new System.Drawing.CharacterRange(0, text.Length) };
            System.Drawing.Region[] regions = new System.Drawing.Region[1];

            format.SetMeasurableCharacterRanges(ranges);

            regions = g.MeasureCharacterRanges(text, f, rect, format);
            rect = regions[0].GetBounds(g);

            return (int)(rect.Right + 1.0f);
        }

0 个答案:

没有答案