2

I am using netDXF (https://netdxf.codeplex.com/) to generate a DXF file for use with AutoCAD. However, I have an issue with getting the width of MText correct. I want to be able to define a width that the text should fit into, and change the width factor of the text (squash it horizontally) so that it fits in the defined area. So if I have a 40mm width to fit the text into and the text is 80mm long, it needs to have a width factor of 0.5. The only problem is that I don't know how to accurately determine the width of the text. I have tried the following methods and was unsuccessful in getting the correct result:

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

I have attached my code. I am basically printing a horizontal line using each of the 3 methods to calculate text width and comparing it to the actual text width. If I change the font, I get varying results. I have attached two images. One using the code with Calibri and one with Arial. I need the line to be on the edges of the text no matter what font I use.

Arial

Calibri Here is my code:

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);
        }
Community
  • 1
  • 1
Asagohan
  • 583
  • 5
  • 19

0 Answers0