27 August 2008

Silverlight and text-align:justify.

Silverlight has no such thing as text-align: justify! There is an explanation, but I'm not buying it, but I believe it will be soon fixed, as well as the right-to-left direction.

Okay, the future is bright, Silverlight is still beta, but I want text justified now. As I was saying, I am working on something more like a website than an application, and I chose HTML overlay to display more text. Still, there's one place where there are a few sentences about my company, that I'd prefer to keep in a stylish Silverlight control. Stylish like this:

Doesn't the bit of text just beg to be justified? It does to me and it's fortunately short so I can justify it by hand. So, here are a few tries, read on to learn about my adventures in text justifying or scroll down to the last one to see what finally worked.

First, I manually split the texblock into a few smaller ones, one for each line. Then I just assigned the the right width. Result below:

Well, the texblocks do have the required width, as you see on the framed one, but the text inside doesn't.

Second try: scaling them horizontally with a transformation. Take Blender, type the right thing (1.1) in the right box, like this:

And you get this:

So it's scaled. But: now it goes further on both sides. I just wanted to extend it to the right. We could now push it to the right too, but that would be a mess to find the right values for both transformations. There's a much easier way: move the origin point. It's by default at the center of the obeject, thus the RenderTransformOrigin="0.5,0.5". Setting it to "0,0" will move it to the left top corner. As we're not scaling vertically, we don't care about the top coordinate, so let's just put "0,0". Now all there is to do is find the right scale, I just binary searched between 1 and 1.1. The first line, for instance, got 1.03:

Here's the final result: six delightfully justified lines.
Phew, we're done. So that was a bit of work, but it was okay for such a short text. However, if the width of the frame was to change, I'd have to start all over! Split the textblock in lines again and scale each line again. If someone feels like it, you can try and write a piece of code that would do that programmatically. Yes, MS developers, I'm talking to you.

1 comment:

  1. You should programatically split the entire text into individual textblocks containing single words plus immediate punctuation (don't split the period from the last word at the end of a sentence, etc). Then use MeasureOverride and ArrangeOverride to figure out how big each textblock is and figure out which ones fit onto a single line. Then figure out how many pixels you are short and then spread those pixels either fractionally (which may cause some interpolation) or adding whole pixels between elements. Repeat on the next line, etc. While this is more difficult, it is probably more robust than the solution that you propose.