I’m trying to draw right-aligned text in a canvas.
While drawing left-aligned text with its proper wrapwidth works OK in that when the text reaches wrapwidth itvstarts a new line, when I try drawing right align text and the text reaches wrapwidth, it correctly starts a new line but it also continues to move behind, that is, outside, the left margin and the new line does not start on the right, but on the left.
dim mTop2 as Integer = g.TextHeight
dim r as String = someText
g.DrawText(r, g.Width - g.TextWidth(r) - leftMargin, mTop2, leftMargin-g.width)
For instance, the text: “I go to see my mother somewhere”: according to the given wrapwidth, let us suppose it wraps after “mother”.
I expect to see:
“I go to see my mother
… … … …somewhere” // i.e. at the right margin
But what I see is:
“see my mother
where” //i.e. at the left margin
That is “I go to” (of the first line) and “some” (of the second line) have moved outside the left margin and “where” (of the second line) does not draw from the right margin but from the left margin. And the more I type, the more the text moves outside the left margin till I don’t see anything anymore.
Utterly confused. Can anybody tell me how to properly adjust the “X” and “wrapwidth” values of drawtext?
Thank you.
Unfortunately, you can’t justify multi-line text with a single call to DrawText. You will need to split the paragraph into lines and draw them individually.
The problem that you (and everybody else trying to do this) will have is determining where to perform the split. The simplest method is to build up a string character by character, measure it and then split when its pixel width becomes too long or when you reach a carriage return.
There is a high probability that you will split in the middle of a word so you then need to add logic to determine where each word ends (for example, space or punctuation) and split at the end of the last word that fits. That will probably work for the Latin script but won’t work if you have to process other scripts such as CJK or Thai as they have different word boundary rules.
Doing this properly really needs help from the Xojo framework and i’ve logged enhancements over the years for this functionality to be added but so far those requests have been ignored.
I wrote a solution for that a few years ago for BBCodeLabel.
The string to draw was parsed in a TextStorage class that splits the text by each word, space, punctuation, newline…
A PreProcess method does a fake drawing to identify when drawing needs to go to the next line and the X, Y positions of each line.
Finally, the drawing process would draw each word, adding the width of a space character or tab when needed and querying each line’s X, Y position in order to align correctly the text (left, center, justified, right).
I see. Mainwhile I saw that Language Reference > wrapwidth speaks about splitting a text into lines and feed each line, as you yourself have explained. While I can get the number of lines, I find it too difficult to get the content of each line. So I abandoned the idea. As they used to say, Nondum matura est.
@Eric_Pousse I think that if you replace
dim r as String = someText with
dim r as String = “I go to see my mother” etc.
and run the code-snippet in a canvas, you will see what I clumsily tried to say.