jasperreports
jasperreports copied to clipboard
Overflow bug with general Jasperreports component (magic dot)
Version: latest master and release. Bug: Some texts don't stretch textfield height quite enough to show the full text. Text overflows and stays hidden. This can be fatal for important documents, such as invoices and contracts.
This is how it looks like: (the only difference between texts is that tiny DOT, and it makes BBBBBBBBB in first field invisible)
How to reproduce:
- Unzip provided FontsReport.jrxml and replace "jasperreports/demo/samples/fonts/reports/FontsReport.jrxml" with it. FontsReport.zip
- Build fonts sample with ant
- Check ./build/reports/FontsReport.pdf
You can set the net.sf.jasperreports.export.pdf.force.linebreak.policy property to true to avoid the problem.
You can also consider creating a font extension for the Arial font.
@dadza I don't think that this is due to external Arial font. Bug exists even with DejaVu fonts shipped with the server. This also fails:
<font fontName="DejaVu Sans" size="8"/>
Changed font from Arial to DejaVu Sans and font size from 9 to 8.
And this is not PDF bug, because xls and other formats overflow too. So this is comprehensive all around bug affecting all formats and fonts.
Does net.sf.jasperreports.export.pdf.force.linebreak.policy have any effect?
no
Any news on this ? My users keep reporting to me about "text is not visible" and when I check why - it is always due to this bug. Can you guys replicate this bug ? Can you tell me where in the code letter-and-text-size-calculation done ?
UPDATE: this is not "dot" bug, I have examples with texts without dot and it overflows it's container and last part of the text is not visible.
The report that you attached renders properly for me with net.sf.jasperreports.export.pdf.force.linebreak.policy=true, see attached PDFs. Is there another report that illustrates the problem that you see?
@dadza sorry, you were right, enabling net.sf.jasperreports.export.pdf.force.linebreak.policy=true somehow fixes it, but this is not a solution, because this policy is bad, it makes text less readable and also it does not fix export to Excel format (for example).
So, according to reference (https://jasperreports.sourceforge.net/config.reference.html#net.sf.jasperreports.export.pdf.force.linebreak.policy), it makes this: "Property that specifies whether the PDF exporter should use a [SplitCharacter] implementation to ensure that PDF text wrap behavior is the same as in AWT." What is AWT ? Abstract Window Toolkit ? So now I can assume that jasper reports library internally calculates text sizes using AWT and so breaks line on dots and (according to my tests) other non-alphabetical symbols?
How to disable this policy inside AWT/jasper and make text size calculation more "normal" ?
I found text measuring code inside src/net/sf/jasperreports/engine/fill/SimpleTextLineWrapper.java:
protected int measureExactLineBreakIndex(float width, int endLimit, boolean requireWord)
{
//FIXME would it be faster to create and cache a LineBreakMeasurer for the whole paragraph?
Map<Attribute, Object> attributes = new HashMap<>();
// we only need the font as it includes the size and style
attributes.put(TextAttribute.FONT, fontInfo.fontInfo.font);
String textLine = paragraphText.substring(paragraphPosition, endLimit);
AttributedString attributedLine = new AttributedString(textLine, attributes);
// we need a fresh iterator for the line
BreakIterator breakIterator = paragraphTruncateAtChar ? BreakIterator.getCharacterInstance()
: BreakIterator.getLineInstance();
LineBreakMeasurer breakMeasurer = new LineBreakMeasurer(attributedLine.getIterator(),
breakIterator, context.getFontRenderContext());
int breakIndex = breakMeasurer.nextOffset(width, endLimit - paragraphPosition, requireWord)
+ paragraphPosition;
if (logTrace)
{
log.trace("exact line break index measured at " + (paragraphOffset + breakIndex));
}
return breakIndex;
}
The problem is in BreakIterator.getLineInstance(), according to java reference (https://docs.oracle.com/javase/8/docs/api/java/text/BreakIterator.html) and my tests it breaks line on almost any non-alphanumeric symbol, and such idiotic line breaking rules are not supported by exporters (except "fixed" pdf exporter).
To fix this bug, line breaker should break only on space. I tested jasper with word breaker: BreakIterator.getWordInstance() but it fails too, because it breaks line on non-alphanumeric symbols too.
So, best solution would be to write custom BreakIterator which breaks line only on space symbols, I searched for custom BreakIterator examples but found nothing, I'm not professional enough in Java and can't write it from scratch. Can anybody help me with this ?
One option is to switch to ICU4J as locale provider. To do that, include icu4j and icu4j-localespi jars in your classpath and set the java.locale.providers
Java system property to SPI,CLDR,COMPAT
(as in java -Djava.locale.providers=SPI,CLDR,COMPAT ...
).
I can't say though if the ICU4J line breaking rules would meet your expectations.
@dadza i think ICU4J will make it even worse, adding even more language-related word breaks.
I managed to fix it manually by rewriting that measureExactLineBreakIndex method. However, this did not solve the problem. It turned out that this class method is not the only responsible for measuring the size of the text... Oh...
Namely, the text inside the Table component is not measured by this measureExactLineBreakIndex method.
For me, it turned out to be a surprise that table texts are not measured by LineBreakMeasurer either. (I checked all LineBreakMeasurer instances in Jasper code and failed to find where it is done).
Do you know where table texts are measured ?
There is nothing special about table texts.
All texts are measured by either SimpleTextLineWrapper or ComplexTextLineWrapper, depending on several attributes (whether the text has attribute styles, tab stops, and so on). Then in SimpleTextLineWrapper there are multiple places where texts are measured.
So if you want to change the way text are measured you'll need to change more than the measureExactLineBreakIndex method.
I think that the initial issue has been solved by using the net.sf.jasperreports.export.pdf.force.linebreak.policy configuration property, which made AWT and PDF text rendering match. Additional issues related to how AWT performs word wrapping should be tracked separately, if really needed.
Thank you, Teodor