Calculating Text Metrics for TextBox in Word Document

Home Forums Open-Xml-Sdk Calculating Text Metrics for TextBox in Word Document

This topic contains 2 replies, has 2 voices, and was last updated by  tdemay 7 years, 9 months ago.

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #3586

    tdemay
    Participant

    What’s the best way to calculate dimensions for a TextBox given the text and font.

    In other words, how do I calculate cx and cy for wp:extent for a wps:txbx ?

    I’m trying to add a watermark to a word document using OpenXML SDK in C# and .Net 4.0

    Inputs are
    Font, FontSize, Bold, Italics, Text, Rotation, Position (horizontal and vertical on page), Text Alignment, Color

    I’ve got everything working… I just need to calculate the size of the text box.

    #3591

    Eric White
    Keymaster

    This is a non-trivial (but doable) task.

    After many experiments, I found that the text metrics methods in System.Windows.Forms.TextRenderer gave me the best results. This is the text metric functionality that WmlToHtmlConverter uses. You can look at the code in WmlToHtmlConverter as one example of the use of TextRenderer.

    Dealing with rotation means that you will need to remember your basic trigonometry from high school. 🙂

    #3596

    tdemay
    Participant

    Thanks for your immediate response. I built the extension method below from your example in WmlToHtmlConverter.cs. Posting it here for anyone that might need it.

    Let me know if you have any thoughts on this. I doubled the font size because for some reason I don’t understand the FontSize that is used in the <w:sz> elements for the TextBox is doubled in the XML than what the user sees in the FontSize drop down in the UI.

    
            public static D.Size GetTextSize(this CWatermarkItemBase watermark, string runText)
            {
                D.FontStyle fs = D.FontStyle.Regular;
                if (watermark.FontBold) fs |= D.FontStyle.Bold;
                if (watermark.FontItalic) fs |= D.FontStyle.Italic;
                var sz = watermark.FontSize * 2;
                var proposedSize = new D.Size(int.MaxValue, int.MaxValue);
                D.Size sf;
    
                using (var ff = new D.FontFamily(watermark.FontFamily))
                {
                    try
                    {
                        using (var f = new D.Font(ff, (float)sz, fs))
                        {
                            const TextFormatFlags tff = TextFormatFlags.NoPadding;
                            sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                        }
                    }
                    catch (ArgumentException)
                    {
                        try
                        {
                            const D.FontStyle fs2 = D.FontStyle.Regular;
                            using (D.Font f = new D.Font(ff, (float)sz, fs2))
                            {
                                const TextFormatFlags tff = TextFormatFlags.NoPadding;
                                sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                            }
                        }
                        catch (ArgumentException)
                        {
                            const D.FontStyle fs2 = D.FontStyle.Bold;
                            try
                            {
                                using (var f = new D.Font(ff, (float)sz, fs2))
                                {
                                    const TextFormatFlags tff = TextFormatFlags.NoPadding;
                                    sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                                }
                            }
                            catch (ArgumentException)
                            {
                                // if both regular and bold fail, then get metrics for Times New Roman
                                // use the original FontStyle (in fs)
                                using (var ff2 = new D.FontFamily("Times New Roman"))
                                using (var f = new D.Font(ff2, (float)sz, fs))
                                {
                                    const TextFormatFlags tff = TextFormatFlags.NoPadding;
                                    sf = TextRenderer.MeasureText(runText, f, proposedSize, tff);
                                }
                            }
                        }
                    }
                }
                const int multiplier = 5000;
                return new D.Size(sf.Width * multiplier, sf.Height * multiplier);
            }
    
Viewing 3 posts - 1 through 3 (of 3 total)

You must be logged in to reply to this topic.