Website may be up and down over next few months. I'm currently doing a complete overhaul of everything. Going back to simple individual .htm pages, new overall site theme, sanitizing and cleaning up html of all pages and blog posts, attempting to implement a new tooling and publishing system etc etc.

DrawString Code Snip

This xna code snip allows you to draw text, with the option of having that text word wrapped to the specified rectangle or you can specify text alignment info like weather or not the text should be drawn anchored to the bottom right of the rectangle or top right etc.

Keep in mind that this code is not optomized and need to be redone. Drawing lots of strings using this code will result in signifigant slowdown.

 

    public enum TextAlignment
    {
        Top,
        Left,
        Middle,
        Right,
        Bottom,
        TopLeft,
        TopRight,
        BottomLeft,
        BottomRight
    }
 
 
        /// <summary>
        /// Draws a string.  
        /// </summary>
        /// <param name="sb">A reference to a SpriteBatch object that will draw the text.</param>
        /// <param name="fnt">A reference to a SpriteFont object.</param>
        /// <param name="text">The text to be drawn. <remarks>If the text contains \n it 
        /// will be treated as a new line marker and the text will drawn acordingy.</remarks></param>
        /// <param name="r">The screen rectangle that the rext should be drawn inside of.</param>
        /// <param name="col">The color of the text that will be drawn.</param>
        /// <param name="align">Specified the alignment within the specified screen rectangle.</param>
        /// <param name="performWordWrap">If true the words within the text will be aranged to rey and 
        /// fit within the bounds of the specified screen rectangle.</param>
        /// <param name="offsett">Draws the text at a specified offset relative to the screen 
        /// rectangles top left position. </param>
        /// <param name="textBounds">Returns a rectangle representing the size of the bouds of 
        /// the text that was drawn.</param>
          public static void DrawString(SpriteBatch sb, SpriteFont fnt, string text, Rectangle r,
          Color col, TextAlignment align, bool performWordWrap, Vector2 offsett, out Rectangle textBounds)
        {
            // check if there is text to draw
            textBounds = r;
            if (text == null) return;
            if (text == string.Empty) return;
 
            StringCollection lines = new StringCollection();
            lines.AddRange(text.Split(new string[] { "\\n"}, StringSplitOptions.RemoveEmptyEntries));
 
            // calc the size of the rect for all the text
            Rectangle tmprect = ProcessLines(fnt, r, performWordWrap, lines);
 
            // setup the position where drawing will start
            Vector2 pos = new Vector2(r.X, r.Y);
            int aStyle = 0;
 
            switch (align)
            {
                case TextAlignment.Bottom:
                    pos.Y = r.Bottom - tmprect.Height;
                    aStyle = 1;
                    break;
                case TextAlignment.BottomLeft:
                    pos.Y = r.Bottom - tmprect.Height;
                    aStyle = 0;
                    break;
                case TextAlignment.BottomRight:
                    pos.Y = r.Bottom - tmprect.Height;
                    aStyle = 2;
                    break;
                case TextAlignment.Left:
                    pos.Y =  r.Y + ((r.Height / 2) - (tmprect.Height / 2));
                    aStyle = 0;
                    break;
                case TextAlignment.Middle:
                    pos.Y =  r.Y + ((r.Height / 2) - (tmprect.Height / 2));
                    aStyle = 1;
                    break;
                case TextAlignment.Right:
                    pos.Y = r.Y + ((r.Height / 2) - (tmprect.Height / 2));
                    aStyle = 2;
                    break;
                case TextAlignment.Top:
                    aStyle = 1;
                    break;
                case TextAlignment.TopLeft:
                    aStyle = 0;
                    break;
                case TextAlignment.TopRight:
                    aStyle = 2;
                    break;
            }
 
            // draw text
            for (int idx = 0; idx < lines.Count; idx++)
            {
                string txt = lines[idx];
                Vector2 size = fnt.MeasureString(txt);
                switch (aStyle)
                {
                    case 0:
                        pos.X = r.X;
                        break;
                    case 1:
                        pos.X = r.X + ((r.Width / 2) - (size.X / 2));
                        break;
                    case 2:
                        pos.X = r.Right - size.X;                       
                        break;
                }
                // draw the line of text
                sb.DrawString(fnt, txt, pos + offsett, col);
                pos.Y += fnt.LineSpacing;
            }
 
            textBounds = tmprect;
        }
 
        internal static Rectangle ProcessLines(SpriteFont fnt, Rectangle r, bool performWordWrap, StringCollection lines)
        {
            // llop through each line in the collection
            Rectangle bounds = r;
            bounds.Width = 0;
            bounds.Height = 0;
            int index = 0;
            float Width = 0;
            bool lineInserted = false;
            while (index < lines.Count)
            {
                // get a line of text
                string linetext = lines[index];
                //measure the line of text
                Vector2 size = fnt.MeasureString(linetext);
 
                // check if the line of text is geater then then the rect we want to draw it inside of
                if (performWordWrap && size.X > r.Width)
                {
                    // find last space character in line
                    string endspace = string.Empty;
                    // deal with trailing spaces
                    if (linetext.EndsWith(" "))
                    {
                        endspace = " ";
                        linetext = linetext.TrimEnd();
                    }
 
                    // get the index of the last space character
                    int i = linetext.LastIndexOf(" ");
                    if (i != -1)
                    {
                        // if there was a space grab the last word in the line
                        string lastword = linetext.Substring(i + 1);
                        // move word to next line 
                        if (index == lines.Count - 1)
                        {
                            lines.Add(lastword);
                            lineInserted = true;
                        }
                        else
                        {
                            // prepend last word to begining of next line
                            if (lineInserted)
                            {
                                lines[index + 1] = lastword + endspace + lines[index + 1];
                            }
                            else
                            {
                                lines.Insert(index + 1, lastword);
                                lineInserted = true;
                            }
                        }
 
                        // crop last word from the line that is being processed
                        lines[index] = linetext.Substring(0, i + 1);
 
                    }
                    else
                    {
                        // there appear to be no space characters on this line s move to the next line
                        lineInserted = false;
                        size = fnt.MeasureString(lines[index]);
                        if (size.X > bounds.Width) Width = size.X;
                        bounds.Height += fnt.LineSpacing;// size.Y - 1;
                        index++;
                    }
                }
                else
                {
                    // this line will fit so we can skip to the next line
                    lineInserted = false;
                    size = fnt.MeasureString(lines[index]);
                    if (size.X > bounds.Width) bounds.Width = (int)size.X;
                    bounds.Height += fnt.LineSpacing;//size.Y - 1;
                    index++;
                }
            }
 
            // returns the size of the text
            return bounds;
        }

Creative Commons License
This work by Dean Lunz is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.5 Canada License. Permissions beyond the scope of this license may be available at http://contact.createdbyx.com/.

Created by: X

Just another personal website in this crazy online world

Name of author Dean Lunz (aka Created by: X)
Computer programming nerd, and tech geek.
About Me -- Resume