This article will demonstrate the use of
MeasureCharacterRanges to draw a string a character at a time. Not very exciting, I hear you cry. Bear with me.
I wrote this short article after seeing a question posted on a newsgroup about being able to draw text along a curve. While drawing a character at a time is easy, I wanted to make sure the character spacing was maintained.
Just set up some text to work with:
string measureString = "This is a test string.";
int numChars = measureString.Length;
Initialize the character ranges array, this is used to delimit the blocks of characters in the string, in this example, each character is a 'range'.
Now, initialize the
StringFormatFlags, I'm using the
NoClips flag to ensure that the character is not clipped when drawing.
StringFormat stringFormat = new StringFormat();
stringFormat.FormatFlags = StringFormatFlags.NoClip;
Set up an array to hold the calculated regions:
Region stringRegions = new Region[numChars];
for(int i = 0; i<numChars; i++)
characterRanges[i] = new CharacterRange(i, 1);
Create a font, and use
MeasureCharacterRanges() to calculate the regions for the character ranges.
The regions returned by
MeasureCharacterRanges are converted to rectangles by using the
GetBounds() function. The rectangle can then be manipulated using offset or any other method to adjust its placement.
In this example, I offset the Y position using a random amount to give wavy text.
using (Font stringFont = new Font("Times New Roman", 16.0F))
SizeF size = g.MeasureString(measureString, stringFont );
RectangleF layoutRect =
new RectangleF( 0.0f, 0.0f, size.Width, size.Height);
stringRegions = g.MeasureCharacterRanges(
Random rand = new Random();
for ( int indx = 0 ; indx < numChars; indx++ )
Region region = stringRegions[indx] as Region;
RectangleF rect = region.GetBounds(g);
rect.Offset( 0f, (float) rand.Next(100) / 10f);
stringFont, Brushes.Yellow, rect, stringFormat );
As I said at the beginning, this is not the most efficient code, the calculations could be done outside the drawing routine and cached. However, I hope this demonstrates how easy it is to determine the character positions.