Issues with the Justification and Labels


#1

Hello Jules !

I have a problem with the way the Labels display the text. In my software Inspiration, I have large Labels with text centered horizontally and vertically. And I’m using the function setMinimumHorizontalScale(1.f) so the text is never squashed (which may look ugly in this context).

However, I have sometimes bad surprises :

  • The height of the label is large, but the end of the text may be cut and replaced with ellipsis, in spite of the possibility to finish the word at a new line
  • Some words in the middle of the text are cut in half randomly at the end of a line, when the last word of the last line is near the margin
  • The number of lines used to display the whole text may even be too important, which is a thing occuring frequently when I’m trying to justify some text on the left side

I had less problems with setMinimumHorizontalScale(0.99f) for example, but these issues appear randomly for some entries in my software Inspiration

So, I’m wondering if these problems are linked with JUCE or not, and if I can do something to have my text in Labels correctly displayed systematically…

Thanks in advance !


#2

If you need more control than a label gives you, you could always use your own TextLayout object, and just draw it?


#3

Well, I have written a workaround for this issue, a component which is analyzing the text and calculating the places where the new lines must be put, using the function Font::getStringWidth(). The same thing may be done with a TextLayout object (and the draw function code would be the same).

However, what I’m talking about isn’t a lack of available control in the Label component, at first it looks like a bug or a random behaviour doesn’t it ? :mrgreen: I mean, is it normal for a standard label component to cut words and to add new lines randomly in the display ?


#4

How can I tell from your description? I obviously use labels a lot, but I’ve never seen one cut off any text, except when it’s not big enough to actually fit everything in.


#5

My description is clear I think. Here is a screen capture of what is happening :

https://dl.dropbox.com/s/d1aitb3xcq6zsb6/BugInspiration.png?dl=1

In Photoshop, I have added a rectangle in magenta to show the size of the label. And there, instead of putting the last character on a new line, the Label display a cut version of the text. If I put an additional space between words, the text looks okay, and is displayed on three lines. I had the same problem several times with english strings too. I think this phenomenum happens when the last word is at the limit of being squashed, and it happens all the time for a given string and given bounds.

Moreover, Jules, please, each time I want to submit anything here, I feel like I’m in a court of justice, needing to argue against the “you have done a stupid request” assertion, before my request can be just considered a little. I’m following Tracktion and JUCE for several years now, my firm has bought JUCE licences because of me, so I think I deserve minimal respect. I may post some stupid requests sometimes, or irrelevant, but even if it’s the case, there are respectful ways to tell that to people. And this request this time is not one.


#6

That doesn’t look like the internal juce layout engine, so you might be on Windows, using DirectWrite? If so, there’s nothing much I can do about Microsoft’s algorithm, but you can disable directwrite if you don’t need right-to-left support, and the juce layout stuff might do a better job.

Sorry, but please don’t confuse hastiness with grumpiness! I’d love to spend a long time chatting about each question and the background of the person who’s asking it, etc. But realistically, I can just about manage to keep up if I skim-read the questions and hammer out very quick replies…


#7

I agree with you that it would be impossible for you to continue the development of JUCE and chat for hours with every people for every single request. But I still think that what you call hastiness is sometimes irrespectful, that’s how I feel about it several times. Moreover, I think that you may even gain some time if you put the right consideration into some relevant requests, because you would be able to understand the point sooner. This is of course also depending on the JUCE forum users, who have to describe the most relevant way their problems.

I have exactly the same problem with Windows XP, in the same conditions, my application being multi-platform, with the DirectWrite macro disabled everywhere.


#8

Well why don’t you just write your own Label?


#9

Well, it’s definitely not intentional or personal! And please bear in mind that it’s not always obvious which questions deserve a deeper look… This one could still be something simple, or something more sinister. In fact, I’m still not sure which it is.

I started off skeptical because like I said, I’ve never seen a label do that, and I’m pretty sure that the layout code can only split text on word boundaries. But your screenshot is really puzzling - I can’t imagine why it would behave like that.

Can you perhaps give me a code-snippet that does the same thing?


#10

Okay :wink:

So the code, here it is (just tried in a new JUCE project for Windows, with DirectWrite disabled, compiled on VS2008) :

[code]MainComponent::MainComponent()
{ addAndMakeVisible(labelTest = new Label("", “”));
labelTest->setJustificationType(Justification::centred);
labelTest->setFont(Font(“Verdana”, 16, 0));
labelTest->setMinimumHorizontalScale(1.f);

labelTest->setText("Considere la piece comme une serie d'evenements plutot que l'empilement de couches", false);

setSize(500, 350);

}

MainComponent::~MainComponent()
{ deleteAllChildren();
}

void MainComponent::paint(Graphics &g)
{
}

void MainComponent::resized()
{ labelTest->setBounds(100, 95, getWidth()-200, 96);
}
[/code]

This code produces exactly the thing I’m talking about.

Well, I have done it yet. But I don’t like the idea of fixing bugs in a library without telling the library creator something about them. I don’t like the idea of creating alternative stuff too often either. And I may forget about this bug in a few years in a new project also !


#11

Just had a look at this - there’s no actual bug involved. It’s just happening because the algorithm that tries to find line-break positions is deciding that the word “d’evenements” is too long, and is splitting it. It’s just a freak case because of your particular sentence structure, and where the long word happens to be positioned within the label, and the fact that you disabled the horizontal scaling.

There’s nothing actually wrong with the algorithm, but looking at it again, the tolerance for word-length is probably a bit conservative, so I’ve tweaked the number slightly to make it look a bit further for whitespace before giving up, which will probably avoid edge-cases like this one.


#12

[quote]Just had a look at this - there’s no actual bug involved. It’s just happening because the algorithm that tries to find line-break positions is deciding that the word “d’evenements” is too long, and is splitting it. It’s just a freak case because of your particular sentence structure, and where the long word happens to be positioned within the label, and the fact that you disabled the horizontal scaling.

There’s nothing actually wrong with the algorithm, but looking at it again, the tolerance for word-length is probably a bit conservative, so I’ve tweaked the number slightly to make it look a bit further for whitespace before giving up, which will probably avoid edge-cases like this one.[/quote]
Thanks for the explanation and the correction :wink:

Anyway, I’m not really understanding why you have chosen a kind of arbitrary tolerance on word-length (if I have understood well what you have said).

For me, your algorithm should always look for a white space to create a new line, with only one exception. This exception may be a word, alone, which uses the whole line for itself, and which is of course too long to be displayed fully on this line.

For me again, with two very long words, in a very large label, which may be displayed fully if they were each taken alone, the new line should be between these two long words, and not in the middle of the last long word. This way, there is no more arbitrary tolerance which is not dependent on the width of the label, and any text with an actual meaning using words with any length, in a large enough label, will always be displayed “correctly”.

Your algorithm (the way I have understood what you said) (the = represents the label width)

Before the algorithm
==============================================================================
sdsdgsgdsdghsdsdjkshdjksghsdjsdhkjshdjdsdghsgdsghd sjdsjkhdjsghdhsgdhsghhsgdhsgdsgdjshdhsjdsgdsdizdiojhdzhd

After the algorithm (tolerance equals says 20 characters)
==============================================================================
sdsdgsgdsdghsdsdjkshdjksghsdjsdhkjshdjdsdghsgdsghd sjdsjkhdjsghdhsgdhsghhsgdhs
gdsgdjshdhsjdsgdsdizdiojhdzhd

My point of view :

Before the algorithm
==============================================================================
sdsdgsgdsdghsdsdjkshdjksghsdjsdhkjshdjdsdghsgdsghd sjdsjkhdjsghdhsgdhsghhsgdhsgdsgdjshdhsjdsgdsdizdiojhdzhd

After the algorithm
==============================================================================
sdsdgsgdsdghsdsdjkshdjksghsdjsdhkjshdjdsdghsgdsghd 
sjdsjkhdjsghdhsgdhsghhsgdhsgdsgdjshdhsjdsgdsdizdiojhdzhd

I’m afraid about having the same problem happening again in the future with a normal word being too long again.

What do you think about my point of view ?

I imagine the ideal way to do the work for a typography specialist would be to consider hyphenation, but this is dependent on language and of a dictionnary content, so this is a wrong idea for me to try going there :mrgreen:

Anyway, your solution may do the trick, and I think the chances for the issue I have been reporting to happen again are under 0.00001 % :stuck_out_tongue:


#13

The algorithm’s pretty complex and would be easy to break if I started messing with it - if the problem wasn’t so unusual I’d consider it, but it really is a bit of an edge-case.


#14

Okay :mrgreen: I imagine the HorizontalScale part is one of the things that complicates the algorithm…


#15

Hmmmm… (I have just taken the last JUCE with GIT)

https://dl.dropbox.com/s/87cb9ycoee0gxd4/BugInspiration2.png?dl=1

The example of before with the new text does that too :mrgreen:


#16

[quote=“Wolfen”]Hmmmm… (I have just taken the last JUCE with GIT)

https://dl.dropbox.com/s/87cb9ycoee0gxd4/BugInspiration2.png?dl=1

The example of before with the new text does that too :mrgreen:[/quote]

How certain are you that you really did build with the latest version? In your picture the algorithm has split the word after 6 characters, but I changed it to scan at least 7.


#17

100%. I have taken the last files on GIThub today, I have verified once again that everything is updated, and this is the case. Moreover, as you can see on the picture, there are 3 points at the end of the text…


#18

Hello Jules !

I have a proposal :mrgreen:

So, the algorithm from the last tip produces the following results :

http://wolfen.ivan.free.fr/Inspiration-OldAlgo1.png
http://wolfen.ivan.free.fr/Inspiration-OldAlgo2.png

As you can see, there are two issues here. In the first image, as I said in my first post, the new line characters are not in the right place. Several words should be in the previous lines. It’s not really a bug, but this is a serious problem if someone wants to display the right way large sections of text in Labels. In a program I have developed, I am trying to display various kinds of objects, like in a web page, and this is not really beautiful… In the second image, you can see the problem we have been talking about in the last posts.

So I propose the following code change in the function drawFittedText :

[code]void Graphics::drawFittedText (const String& text, const Rectangle& area,
const Justification& justification,
const int maximumNumberOfLines,
const float minimumHorizontalScale) const
{
if (text.isNotEmpty() && (! area.isEmpty()) && context.clipRegionIntersects (area))
{
GlyphArrangement arr;

if (minimumHorizontalScale == 1.f)
{ arr.addJustifiedText (context.getFont(), text,
(float) area.getX(), (float) area.getY(),
(float) label.getVerticalBorderSize(),
(float) area.getWidth(),
justification);

		arr.justifyGlyphs(0, arr.getNumGlyphs(), 
			(float) area.getX(), (float) area.getY(),
            (float) area.getWidth(), (float) area.getHeight(),
            justification);
	}
	else
	{	arr.addFittedText (context.getFont(), text,
                       (float) area.getX(), (float) area.getY(),
                       (float) area.getWidth(), (float) area.getHeight(),
                       justification,
                       maximumNumberOfLines,
                       minimumHorizontalScale);
	}

    arr.draw (*this);
}

}[/code]

As a result, we got that :

http://wolfen.ivan.free.fr/Inspiration-NewAlgo1.png
http://wolfen.ivan.free.fr/Inspiration-NewAlgo2.png

What do you think ? I have done that in a Custom LookAndFeel, but I think this has to be in the Graphics class code…

Thanks a lot !


#19

For me to change the algorithm used by a basic, long-standing Graphics method that’s called by many thousands of different pieces of code, just because one person wants different behaviour in one particular use-case of that function would not be a responsible way to run a library! That’s what custom L+Fs are for!


#20

Okay, but what do you think of the differences between the two algorithms displayed in my images ? If any user is aware of this issue, and has the choice between the two behaviours, I don’t think he would choose an algorithm which justifies text randomly on height and cut words randomly between each new line.

And I’m sorry, but we are not talking about “one person (who) wants different behaviour in one particular use-case of that function”, your drawFittedText function is wrong when the minimumScale is equal to one, that’s a fact, not something subjective ! I have tons of other examples displaying wrong things ! It happens all the time for labels displaying large portions of text.