From 1df6a1ea16cb4e79585c4eddf250de9fddd971fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Prante?= Date: Mon, 28 Aug 2023 17:55:45 +0200 Subject: [PATCH] fix table font handling with base font's notorious illegal argument exception, fix other table font bugs --- gradle.properties | 2 +- .../pdfbox/layout/element/Document.java | 4 ++ .../pdfbox/layout/table/AbstractTextCell.java | 2 +- .../table/render/AbstractCellRenderer.java | 3 + .../layout/table/render/TextCellRenderer.java | 8 +-- .../render/VerticalTextCellRenderer.java | 2 +- .../graphics/pdfbox/layout/util/PdfUtil.java | 11 +-- .../pdfbox/layout/util/RenderUtil.java | 20 +++++- .../pdfbox/layout/test/table/TableTest.java | 2 +- .../pdfbox/layout/test/scriptingtable.json | 70 ++++++++++++++++++- 10 files changed, 107 insertions(+), 17 deletions(-) diff --git a/gradle.properties b/gradle.properties index bb13e2b..0baabe7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group = org.xbib.graphics name = graphics -version = 4.5.6 +version = 4.5.7 org.gradle.warning.mode = ALL diff --git a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/element/Document.java b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/element/Document.java index 693a9f6..257b685 100644 --- a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/element/Document.java +++ b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/element/Document.java @@ -236,6 +236,10 @@ public class Document implements Element, Closeable, RenderListener { return false; } } + + public String toString() { + return name; + } }); } diff --git a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/AbstractTextCell.java b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/AbstractTextCell.java index fc18ec8..abf8796 100644 --- a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/AbstractTextCell.java +++ b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/AbstractTextCell.java @@ -40,7 +40,7 @@ public abstract class AbstractTextCell extends AbstractCell { if (this.textHeight != null) { return this.textHeight; } - this.textHeight = PdfUtil.getFontHeight(getText(), getFontDescriptor()); + this.textHeight = PdfUtil.getFontHeight(getFontDescriptor()); if (parameters.isWordBreak()) { final int size = PdfUtil.getOptimalTextBreakLines(getText(), getFontDescriptor(), getMaxWidth()).size(); final float heightOfTextLines = size * this.textHeight; diff --git a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/AbstractCellRenderer.java b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/AbstractCellRenderer.java index 4ff11b2..05fb976 100644 --- a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/AbstractCellRenderer.java +++ b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/AbstractCellRenderer.java @@ -13,6 +13,9 @@ public abstract class AbstractCellRenderer implements Renderer { protected T cell; + public AbstractCellRenderer() { + } + public AbstractCellRenderer withCell(T cell) { this.cell = cell; return this; diff --git a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/TextCellRenderer.java b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/TextCellRenderer.java index 564e728..ddb6960 100644 --- a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/TextCellRenderer.java +++ b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/TextCellRenderer.java @@ -30,7 +30,7 @@ public class TextCellRenderer extends AbstractCellRe final List lines = calculateAndGetLines(fontDescriptor, cell.getMaxWidth()); for (int i = 0; i < lines.size(); i++) { final String line = lines.get(i); - yOffset -= calculateYOffset(line, fontDescriptor, i); + yOffset -= calculateYOffset(fontDescriptor, i); final float textWidth = PdfUtil.getStringWidth(line, fontDescriptor); if (cell.isHorizontallyAligned(RIGHT)) { xOffset = startX + (cell.getWidth() - (textWidth + cell.getPaddingRight())); @@ -54,9 +54,9 @@ public class TextCellRenderer extends AbstractCellRe return cell.getTextHeight(); } - private float calculateYOffset(String text, FontDescriptor fontDescriptor, int lineIndex) { - return PdfUtil.getFontHeight(text, fontDescriptor) + - (lineIndex > 0 ? PdfUtil.getFontHeight(text, fontDescriptor) * cell.getLineSpacing() : 0f); + private float calculateYOffset(FontDescriptor fontDescriptor, int lineIndex) { + return PdfUtil.getFontHeight(fontDescriptor) + + (lineIndex > 0 ? PdfUtil.getFontHeight(fontDescriptor) * cell.getLineSpacing() : 0f); } private static boolean isNotLastLine(List lines, int i) { diff --git a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/VerticalTextCellRenderer.java b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/VerticalTextCellRenderer.java index 731fed1..bd362d6 100644 --- a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/VerticalTextCellRenderer.java +++ b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/table/render/VerticalTextCellRenderer.java @@ -43,7 +43,7 @@ public class VerticalTextCellRenderer extends AbstractCellRenderer 0 ? PdfUtil.getFontHeight(line, fontDescriptor) * cell.getLineSpacing() : 0f)); + xOffset += (PdfUtil.getFontHeight(fontDescriptor) + (i > 0 ? PdfUtil.getFontHeight(fontDescriptor) * cell.getLineSpacing() : 0f)); drawText(line, fontDescriptor, currentTextColor, xOffset, yOffset, tableRenderContext.getContentStream()); } } diff --git a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/PdfUtil.java b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/PdfUtil.java index 54472d7..9cdf8b6 100644 --- a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/PdfUtil.java +++ b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/PdfUtil.java @@ -61,6 +61,9 @@ public final class PdfUtil { } found = true; } + if (found) { + break; + } } if (!found) { throw new IllegalArgumentException("unable to get width of string " + codepoint); @@ -75,13 +78,11 @@ public final class PdfUtil { * @param fontDescriptor font * @return height of font */ - public static float getFontHeight(String text, FontDescriptor fontDescriptor) { + public static float getFontHeight(FontDescriptor fontDescriptor) { for (Font font : fontDescriptor.getFonts()) { - if (font.canWrite(text)) { - return font.getRegularFont().getFontDescriptor().getCapHeight() * fontDescriptor.getSize() / 1000F; - } + return font.getRegularFont().getFontDescriptor().getCapHeight() * fontDescriptor.getSize() / 1000F; } - throw new IllegalArgumentException("unable to get font height for text " + text + ", fonts = " + fontDescriptor.getFonts()); + throw new IllegalArgumentException("unable to get font height, fonts = " + fontDescriptor.getFonts()); } /** diff --git a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/RenderUtil.java b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/RenderUtil.java index 96e244d..388c9cf 100644 --- a/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/RenderUtil.java +++ b/graphics-pdfbox-layout/src/main/java/org/xbib/graphics/pdfbox/layout/util/RenderUtil.java @@ -10,26 +10,40 @@ import org.xbib.graphics.pdfbox.layout.table.render.PositionedStyledText; import java.awt.Color; import java.io.IOException; import java.io.UncheckedIOException; +import java.util.logging.Level; +import java.util.logging.Logger; public class RenderUtil { + private static final Logger logger = Logger.getLogger(RenderUtil.class.getName()); + private RenderUtil() { } public static void drawText(PDPageContentStream contentStream, PositionedStyledText styledText) { for (Font font : styledText.getFontDescriptor().getFonts()) { + boolean isBeginText = false; if (font.canWrite(styledText.getText())) { try { contentStream.beginText(); + isBeginText = true; contentStream.setNonStrokingColor(styledText.getColor()); - // TODO select correct font style contentStream.setFont(font.getRegularFont(), styledText.getFontDescriptor().getSize()); contentStream.newLineAtOffset(styledText.getX(), styledText.getY()); contentStream.showText(styledText.getText()); contentStream.endText(); + isBeginText = false; contentStream.setCharacterSpacing(0); - } catch (IOException e) { - throw new UncheckedIOException(e); + break; + } catch (IllegalArgumentException | IOException e) { + logger.log(Level.WARNING, e.getMessage()); + if (isBeginText) { + try { + contentStream.endText(); + } catch (IOException ex) { + // ignore + } + } } } } diff --git a/graphics-pdfbox-layout/src/test/java/org/xbib/graphics/pdfbox/layout/test/table/TableTest.java b/graphics-pdfbox-layout/src/test/java/org/xbib/graphics/pdfbox/layout/test/table/TableTest.java index 855592c..fcee2ab 100644 --- a/graphics-pdfbox-layout/src/test/java/org/xbib/graphics/pdfbox/layout/test/table/TableTest.java +++ b/graphics-pdfbox-layout/src/test/java/org/xbib/graphics/pdfbox/layout/test/table/TableTest.java @@ -112,7 +112,7 @@ public class TableTest { .add(TextCell.builder().text("12").paddingTop(15).paddingBottom(25).build()) .build()) .build(); - final float actualFontHeight = PdfUtil.getFontHeight("test", table.getSettings().getFontDescriptor()); + final float actualFontHeight = PdfUtil.getFontHeight(table.getSettings().getFontDescriptor()); assertThat(table.getHeight(), equalTo(50 + actualFontHeight)); } diff --git a/graphics-pdfbox-layout/src/test/resources/org/xbib/graphics/pdfbox/layout/test/scriptingtable.json b/graphics-pdfbox-layout/src/test/resources/org/xbib/graphics/pdfbox/layout/test/scriptingtable.json index 7cb03b5..fc3dba8 100644 --- a/graphics-pdfbox-layout/src/test/resources/org/xbib/graphics/pdfbox/layout/test/scriptingtable.json +++ b/graphics-pdfbox-layout/src/test/resources/org/xbib/graphics/pdfbox/layout/test/scriptingtable.json @@ -3,7 +3,7 @@ "margin": "0 0 0 0", "author": "Jörg Prante", "font": [ - "helvetica" + "helvetica", "sourcesans", "notosans", "notosanscjksc" ], "elements": [ { @@ -147,6 +147,74 @@ ] } ] + }, + { + "type": "table", + "padding": "10 10 10 10", + "columnwidths": "40 150", + "elements": [ + { + "type": "row", + "elements": [ + { + "type": "cell", + "text": "Demotext", + "font": [ + "helvetica", "sourcesans", "notosans", "notosanscjksc" + ], + "fontsize": 11 + }, + { + "type": "cell", + "text": "This is a demo text This is a demo text This is a demo text This is a demo text This is a demo text This is a demo text", + "font": [ + "helvetica", "sourcesans", "notosans", "notosanscjksc" + ], + "fontsize": 11 + } + ] + }, + { + "type": "row", + "elements": [ + { + "type": "cell", + "text": "Demotext", + "font": [ + "helvetica", "sourcesans", "notosans", "notosanscjksc" + ], + "fontsize": 11 + }, + { + "type": "cell", + "text": "Short text", + "font": [ + "helvetica", "sourcesans", "notosans", "notosanscjksc" + ], + "fontsize": 11 + } + ] + }, + { + "type": "row", + "elements": [ + { + "type": "cell", + "text": "Demotext", + "font": "helvetica", + "fontsize": 11 + }, + { + "type": "cell", + "text": "Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text ", + "font": [ + "helvetica", "sourcesans", "notosans", "notosanscjksc" + ], + "fontsize": 11 + } + ] + } + ] } ] }