For example, the label "JmsMessaging.someFunction()", was being drawn as
JmsM
essagi
ng.someFunction()
which caused some of the last line to be drawn out of the plot area.
I tracked the problem down to the private function nextLineBreak() in TextUtilities. It would call the BreakIterator next() method to get the next token, then shorten it until it would fit in the allotted maximum width. The first call to next() would return the index of the '.' in the label, the next would return the index of the ')', and the third would return -1 to indicate it was done.
Here is the original code.
Code: Select all
private static int nextLineBreak(final String text, final int start,
final float width, final BreakIterator iterator,
final TextMeasurer measurer) {
// this method is (loosely) based on code in JFreeReport's
// TextParagraph class
int current = start;
int end;
float x = 0.0f;
boolean firstWord = true;
int newline = text.indexOf('\n', start);
if (newline < 0) {
newline = Integer.MAX_VALUE;
}
while (((end = iterator.next()) != BreakIterator.DONE)) {
if (end > newline) {
return newline;
}
x += measurer.getStringWidth(text, current, end);
if (x > width) {
if (firstWord) {
while (measurer.getStringWidth(text, start, end) > width) {
end--;
if (end <= start) {
return end;
}
}
return end;
}
else {
end = iterator.previous();
return end;
}
}
// we found at least one word that fits ...
firstWord = false;
current = end;
}
return BreakIterator.DONE;
}
Here is the modified code.
Code: Select all
private static int nextLineBreak(final String text, final int start,
final float width, final BreakIterator iterator,
final TextMeasurer measurer) {
// this method is (loosely) based on code in JFreeReport's
// TextParagraph class
int current = start;
int end;
float x = 0.0f;
boolean firstWord = true;
int newline = text.indexOf('\n', start);
if (newline < 0) {
newline = Integer.MAX_VALUE;
}
/***************************************************************************************/
/* HERE IS THE CHANGE */
while (((end = iterator.following(current)) != BreakIterator.DONE)) {
/***************************************************************************************/
if (end > newline) {
return newline;
}
// This gives us the next line, we need to process all of the
// string returned before asking for the next line.
x += measurer.getStringWidth(text, current, end);
if (x > width) {
if (firstWord) {
while (measurer.getStringWidth(text, start, end) > width) {
end--;
if (end <= start) {
return end;
}
}
return end;
}
else {
end = iterator.previous();
return end;
}
}
// we found at least one word that fits ...
firstWord = false;
current = end;
}
return BreakIterator.DONE;
}