private FormattedLine consumeComponents(List <string> components, int startIndex, double desiredWidth, double fontSize) { FormattedLine bestResult = null; int lowCount = 1; int highCount = components.Count() - startIndex; while (highCount >= lowCount) { int testCount = Math.Min(lowCount * 2, (lowCount + highCount) / 2); string testText = String.Join("", components.GetRange(startIndex, testCount)); Size requiredSize = this.getLineSize(testText, fontSize); if (requiredSize.Width <= desiredWidth) { // we found some characters that all fit into one line bestResult = new FormattedLine(testCount, testText, requiredSize); lowCount = testCount + 1; } else { // we tried to use too many characters at once, and they didn't all fit if (bestResult == null) { // We can only get here on the first iteration, when measuring only the first word // If not even the first word fit, then we return it anyway, so the caller knows how much space it needs bestResult = new FormattedLine(testCount, testText, requiredSize); } highCount = testCount - 1; } } return(bestResult); }
public FormattedParagraph FormatParagraph(String text, double desiredWidth, bool allowSplittingWords, double fontSize) { if (text == null || text == "") { return(new FormattedParagraph(new Size(), text)); } // total size of the paragraph Size totalSize = new Size(); // the unsplittable units that we're going to measure List <string> components; int i; if (allowSplittingWords) { components = new List <string>(); for (i = 0; i < text.Length; i++) { components.Add(text.Substring(i, 1)); } } else { string[] words = text.Split(' '); components = new List <string>(); for (i = 0; i < words.Length; i++) { if (i != 0) { components.Add(" "); } components.Add(words[i]); } } List <string> formattedLines = new List <string>(); i = 0; while (i < components.Count()) { // consume as many words as will fit on this line FormattedLine line = consumeComponents(components, i, desiredWidth, fontSize); // add new text formattedLines.Add(line.Text); // update size totalSize.Width = Math.Max(totalSize.Width, line.Size.Width); totalSize.Height += line.Size.Height; // continue to subsequent components i += line.NumComponents; // If a space character wrapped to the next line, we can skip it instead if (i < components.Count) { if (components[i] == " ") { i++; } } } return(new FormattedParagraph(totalSize, String.Join("\n", formattedLines))); }