I needed to be able to specify a width and a string and have a function that would draw that string within the specified width, splitting the string up into different lines when required. Since I couldn't find anything in PDFsharp's standard API, I went and made my own. The function is below. Hopefully it'll help someone.
Note: MigraDocs probably adds support for doing this, but i thought it would be overkill. However, this function is also pretty slow, so if you are in need of speed, I'd recommend looking at MigraDocs.
Code:
/// <summary>
/// Draws a string withing a given width, splitting the string up into lines if needed
/// </summary>
/// <param name="zGFX">The XGraphics object being drawn to</param>
/// <param name="zX">The X cordinate of the bounding box</param>
/// <param name="zY">The Y cordinate of the bounding box</param>
/// <param name="zWidth">The width of the bounding box (the Height is undefined)</param>
/// <param name="zText">The text to be drawn</param>
/// <param name="zFont">The font to be used</param>
/// <param name="zBrush">The brush to be used</param>
/// <param name="zFormat">The XStringFormat object to be used</param>
/// <returns>An XRect structure that defines the bounding box that was used</returns>
private XRect DrawString(XGraphics zGFX, double zX, double zY, double zWidth, string zText, XFont zFont, XBrush zBrush, XStringFormat zFormat)
{
if (zWidth <= 0d || zText.Trim() == "") return new XRect(0d, 0d, 0d, 0d);
// Split the string up into words
List<string> words = new List<string>(zText.Split(' ').AsEnumerable());
// Get the width of each of the words
List<double> words_width = new List<double>();
for (int i = 0; i < words.Count; i++)
{
// If the word is too big truncate it
if (zGFX.MeasureString(words[i], zFont, zFormat).Width > zWidth)
while (zGFX.MeasureString(words[i], zFont, zFormat).Width > zWidth)
words[i].Substring(0, words[i].Length - 1);
// Add the width
words_width.Add(zGFX.MeasureString(words[i], zFont, zFormat).Width);
}
// List of the lines
List<string> lines = new List<string>();
// Holds information on the current line in the for loop below
double curLineWidth = 0;
string curLine = "";
// Holds the width of the largest line
double returnWidth = 0d;
// Organize the words into lines that fit into the specified width
for (int i = 0; i < words.Count; i++)
{
// If we've reached the end of the line
if (words_width[i] + curLineWidth > zWidth)
{
// Add the current line to the line list
lines.Add(curLine.Trim());
// Check to see if this is the biggest line, if so, store the width
if (curLineWidth > returnWidth) returnWidth = curLineWidth;
// Reset the current variables
curLineWidth = 0;
curLine = "";
}
// Add the word to the current line
curLine += " " + words[i];
// Add to the line width
curLineWidth += words_width[i];
}
// Add the last line to the line list
lines.Add(curLine.Trim());
// Check to see if this is the biggest line, if so, store the width
if (curLineWidth > returnWidth) returnWidth = curLineWidth;
// Get the height of each line
double lineHeight = zGFX.MeasureString(lines[0], zFont,zFormat).Height;
// Draw the lines
for (int i = 0; i < lines.Count; i++)
zGFX.DrawString(lines[i], zFont, zBrush, new XRect(zX, zY + lineHeight * i, zWidth, lineHeight), zFormat);
return new XRect(zX, zY, returnWidth, lineHeight * lines.Count);
}