Reputation: 119
Using iText 7.1.3 and trying to add a SVG file into PdfDocument gives an output where texts with length 1 are not rendered. I found where it might be the problem. I please the iText team members to check it.
try {
SvgConverter.drawOnCanvas(svgUrl.openStream(), pdfCanvas_, imageLlx, imageLly);
} catch (IOException e) {
e.printStackTrace();
}
Debugger callings:
processText:255, DefaultSvgProcessor (com.itextpdf.svg.processors.impl)
visit:212, DefaultSvgProcessor (com.itextpdf.svg.processors.impl)
visit:204, DefaultSvgProcessor (com.itextpdf.svg.processors.impl)
visit:204, DefaultSvgProcessor (com.itextpdf.svg.processors.impl)
executeDepthFirstTraversal:153, DefaultSvgProcessor (com.itextpdf.svg.processors.impl)
process:106, DefaultSvgProcessor (com.itextpdf.svg.processors.impl)
process:768, SvgConverter (com.itextpdf.svg.converter)
convertToXObject:555, SvgConverter (com.itextpdf.svg.converter)
convertToXObject:590, SvgConverter (com.itextpdf.svg.converter)
drawOnCanvas:380, SvgConverter (com.itextpdf.svg.converter)
In function processText, in the line for Trim trailing whitespace
trimmedText = SvgTextUtil.trimTrailingWhitespace("A");
for the trimmedText = A (length = 1) returns empty String
/**
* Process the text contained in the text-node
*
* @param textNode node containing text to process
*/
private void processText(ITextNode textNode) {
ISvgNodeRenderer parentRenderer = this.processorState.top();
if (parentRenderer instanceof TextSvgNodeRenderer) {
// when svg is parsed by jsoup it leaves all whitespace in text element as is. Meaning that
// tab/space indented xml files will retain their tabs and spaces.
// The following regex replaces all whitespace with a single space.
//TODO(RND-906) evaluate regex and trim methods
String trimmedText = textNode.wholeText().replaceAll("\\s+", " ");
//Trim leading whitespace
trimmedText = SvgTextUtil.trimLeadingWhitespace(trimmedText);
//Trim trailing whitespace
trimmedText = SvgTextUtil.trimTrailingWhitespace(trimmedText);
parentRenderer.setAttribute(SvgConstants.Attributes.TEXT_CONTENT, trimmedText);
}
}
Upvotes: 0
Views: 471
Reputation: 95888
There indeed is a bug in the trimTrailingWhitespace
you pointed out
public static String trimTrailingWhitespace(String toTrim) {
if(toTrim == null){
return "";
}
int end = toTrim.length();
if (end > 0) {
int current = end - 1;
while (current > 0) {
char currentChar = toTrim.charAt(current);
if (Character.isWhitespace(currentChar) && !(currentChar == '\n' || currentChar == '\r')) {
//if the character is whitespace and not a newline, increase current
current--;
} else {
break;
}
}
if(current == 0){
return "";
}else {
return toTrim.substring(0, current + 1);
}
}else{
return toTrim;
}
}
As the comment //if the character is whitespace and not a newline, increase current
followed by current--;
already indicates, this method is a copy of trimLeadingWhitespace
(where the line after the identical comment indeed increases current
) modified to work at the other end of the String
parameter. Unfortunately, though, the modification was incorrect: If the string has a non-whitespace character at position 0 and thereafter only whitespaces, it erroneously is considered empty.
The fix would be to replace
while (current > 0)
by
while (current >= 0)
and
if(current == 0)
by
if(current < 0)
With that fix the
if (end > 0) {
[...]
}else{
return toTrim;
}
frame around [...]
furthermore becomes unnecessary. And the while
loop could more compactly have been formulated as a for
loop, e.g. like this:
public static String trimTrailingWhitespace(String toTrim) {
if (toTrim == null) {
return "";
}
int current = toTrim.length() - 1;
for ( ; current >= 0; current--) {
char currentChar = toTrim.charAt(current);
if (!(Character.isWhitespace(currentChar) && !(currentChar == '\n' || currentChar == '\r'))) {
break;
}
}
return current < 0 ? "" : toTrim.substring(0, current + 1);
}
Upvotes: 1