I know it was a long time ago that you wrote this request, but didn't notice until now, atleast i wrote a textwrapper using a TCanvas and i guess you could use that. It's quite fast, more or less O(N) where N is the length of the text. TextOut is called once per line and textWidth once per word. No costly copy, Length etc as everything is managed on a char to char basis.
It works opposite to yours, starts from the begining and extracts one word from the text. Each word is then added to the line if the line + the word fits within the maximum width.
Code:
Procedure DrawText(Canvas: TCanvas; Text: String; Width, Height: Integer);
var Char: PChar;
var Last: PChar;
var Seperator: System.Char;
var Line: String;
var Word: String;
var X, Y : Integer;
var SpaceWidth: Integer;
var LineHeight: Integer;
begin
Char:=@Text[1];
Line:='';
Word:='';
SpaceWidth:= Canvas.TextWidth (' ');
LineHeight:= Canvas.TextHeight(' ');
X:=0;
Y:=0;
while Char^ <> #0 do begin
// Start of new line
while Char^ <> #0 do begin
// Save the current position
Last:=Char;
// Reset the word
Word:='';
// Get a new word
while not (Char^ in [#0, #32, #13, ',', '.']) do begin
Word:=Word + Char^;
Inc(Char);
end;
Seperator:=Char^;
// Add the word's width to the line
Inc(X, Canvas.TextWidth(Word));
// Check if the word fits within the width
If X >= Width then begin
// Skip the last word.
Char:=Last;
// Print the text
Canvas.TextOut(0,Y, Line);
// Reset the line
Line:='';
// Reset the line's width
X:=0;
// Increase our vertical position
Y:=Y + LineHeight;
// Check if the next line will reach the vertical limit
IF Y + LineHeight >= Height then Exit;
// Exit the line loop
Break;
end;
// Special case if we reached the end of the text
IF Char^ = #0 then begin
Canvas.TextOut(0,Y, Line + Word);
Exit;
end;
// Add the word and a space to the line
Line:=Line + Word + Seperator;
// Add the space's width
Inc(X, SpaceWidth);
// Skip the space
Inc(Char);
end;
end;
Canvas.TextOut(0,Y, Line);
end;
Edit: Typos
Bookmarks