From 4dfde950546c2b94169e678a475e0bcf07dc6578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=CC=88rg=20Prante?= Date: Tue, 10 Nov 2020 09:32:04 +0100 Subject: [PATCH] update to pdfbox 2.0.21, clean up pdfbox graphics io --- build.gradle | 1 - gradle.properties | 2 +- io-pdfbox/build.gradle | 4 +- .../io/pdfbox/DefaultPaintApplier.java | 14 +- .../graphics/io/pdfbox/PdfBoxGraphics2D.java | 124 +++++++++++------- .../io/pdfbox/DanglingGfxCaseTest.java | 77 ----------- .../graphics/io/pdfbox/MultiPageTest.java | 15 +-- .../graphics/io/vector/VectorGraphics2D.java | 16 +-- layout-pdfbox/build.gradle | 4 +- 9 files changed, 104 insertions(+), 153 deletions(-) delete mode 100644 io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/DanglingGfxCaseTest.java diff --git a/build.gradle b/build.gradle index 8379f09..ef37098 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,6 @@ ext { subprojects { apply plugin: 'java-library' - apply from: rootProject.file('gradle/ide/idea.gradle') apply from: rootProject.file('gradle/compile/java.gradle') apply from: rootProject.file('gradle/test/junit5.gradle') diff --git a/gradle.properties b/gradle.properties index 1dfe0cc..706f043 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ name = graphics version = 3.0.0 gradle.wrapper.version = 6.6.1 -pdfbox.version = 2.0.19 +pdfbox.version = 2.0.21 zxing.version = 3.3.1 reflections.version = 0.9.11 jfreechart.version = 1.5.1 diff --git a/io-pdfbox/build.gradle b/io-pdfbox/build.gradle index 84ef5b0..cffda8a 100644 --- a/io-pdfbox/build.gradle +++ b/io-pdfbox/build.gradle @@ -1,5 +1,5 @@ dependencies { - implementation "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}" + api "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}" testImplementation "org.jfree:jfreechart:${project.property('jfreechart.version')}" testImplementation "org.apache.xmlgraphics:batik-swing:${project.property('batik.version')}" -} \ No newline at end of file +} diff --git a/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/DefaultPaintApplier.java b/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/DefaultPaintApplier.java index 44d9ef6..6693c4f 100644 --- a/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/DefaultPaintApplier.java +++ b/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/DefaultPaintApplier.java @@ -77,7 +77,7 @@ public class DefaultPaintApplier implements PaintApplier { state.nestedTransform = null; PDShading shading = applyPaint(paint, state); if (state.pdExtendedGraphicsState != null) { - contentStream.setGraphicsStateParameters(extGStateCache.makeUnqiue(state.pdExtendedGraphicsState)); + contentStream.setGraphicsStateParameters(extGStateCache.makeUnique(state.pdExtendedGraphicsState)); } return shading; } @@ -113,19 +113,19 @@ public class DefaultPaintApplier implements PaintApplier { if (paint instanceof Color) { applyAsStrokingColor((Color) paint, state); } else if (simpleName.equals("LinearGradientPaint")) { - return shadingCache.makeUnqiue(buildLinearGradientShading(paint, state)); + return shadingCache.makeUnique(buildLinearGradientShading(paint, state)); } else if (simpleName.equals("RadialGradientPaint")) { - return shadingCache.makeUnqiue(buildRadialGradientShading(paint, state)); + return shadingCache.makeUnique(buildRadialGradientShading(paint, state)); } else if (simpleName.equals("PatternPaint")) { applyPatternPaint(paint, state); } else if (simpleName.equals("TilingPaint")) { logger.log(Level.WARNING, "no tiling paint available"); } else if (paint instanceof GradientPaint) { - return shadingCache.makeUnqiue(buildGradientShading((GradientPaint) paint, state)); + return shadingCache.makeUnique(buildGradientShading((GradientPaint) paint, state)); } else if (paint instanceof TexturePaint) { applyTexturePaint((TexturePaint) paint, state); } else if (paint instanceof ShadingPaint) { - return shadingCache.makeUnqiue(importPDFBoxShadingPaint((ShadingPaint) paint, state)); + return shadingCache.makeUnique(importPDFBoxShadingPaint((ShadingPaint) paint, state)); } else { logger.log(Level.WARNING, "Don't know paint " + paint.getClass().getName()); } @@ -148,12 +148,10 @@ public class DefaultPaintApplier implements PaintApplier { PDTilingPattern pattern = new PDTilingPattern(); pattern.setPaintType(PDTilingPattern.PAINT_COLORED); pattern.setTilingType(PDTilingPattern.TILING_CONSTANT_SPACING_FASTER_TILING); - pattern.setBBox(new PDRectangle((float) anchorRect.getX(), (float) anchorRect.getY(), (float) anchorRect.getWidth(), (float) anchorRect.getHeight())); pattern.setXStep((float) anchorRect.getWidth()); pattern.setYStep((float) anchorRect.getHeight()); - AffineTransform patternTransform = new AffineTransform(); if (paintPatternTransform != null) { paintPatternTransform = new AffineTransform(paintPatternTransform); @@ -766,7 +764,7 @@ public class DefaultPaintApplier implements PaintApplier { protected abstract int getKey(TObject obj); - TObject makeUnqiue(TObject state) { + TObject makeUnique(TObject state) { int key = getKey(state); List pdExtendedGraphicsStates = states.computeIfAbsent(key, k -> new ArrayList<>()); for (TObject s : pdExtendedGraphicsStates) { diff --git a/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/PdfBoxGraphics2D.java b/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/PdfBoxGraphics2D.java index b69a038..be40faf 100644 --- a/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/PdfBoxGraphics2D.java +++ b/io-pdfbox/src/main/java/org/xbib/graphics/io/pdfbox/PdfBoxGraphics2D.java @@ -68,10 +68,10 @@ import java.util.Map; */ public class PdfBoxGraphics2D extends Graphics2D { - private final PDFormXObject xFormObject; - private final Graphics2D calcGfx; + private final PDFormXObject xFormObject; + private final PDPageContentStream contentStream; private BufferedImage calcImage; @@ -106,12 +106,10 @@ public class PdfBoxGraphics2D extends Graphics2D { private Color backgroundColor; - private final CopyInfo copyInfo; - - private final PDRectangle bbox; - private int saveCounter = 0; + private final CopyInfo copyInfo; + private final List copyList = new ArrayList<>(); private final PaintApplierEnvImpl paintEnv = new PaintApplierEnvImpl(); @@ -163,8 +161,9 @@ public class PdfBoxGraphics2D extends Graphics2D { @Override public void applyPaint(Paint paint, Shape shapeToDraw) throws IOException { PDShading pdShading = PdfBoxGraphics2D.this.applyPaint(paint, shapeToDraw); - if (pdShading != null) + if (pdShading != null) { applyShadingAsColor(pdShading); + } } @Override @@ -174,7 +173,7 @@ public class PdfBoxGraphics2D extends Graphics2D { @Override public PDRectangle getGraphicsBBox() { - return bbox; + return xFormObject.getBBox(); } @Override @@ -202,7 +201,8 @@ public class PdfBoxGraphics2D extends Graphics2D { * @throws IOException if something goes wrong with writing into the content stream of * the {@link PDDocument}. */ - public PdfBoxGraphics2D(PDDocument document, int pixelWidth, int pixelHeight) throws IOException { + public PdfBoxGraphics2D(PDDocument document, int pixelWidth, int pixelHeight) + throws IOException { this(document, new PDRectangle(pixelWidth, pixelHeight)); } @@ -235,15 +235,20 @@ public class PdfBoxGraphics2D extends Graphics2D { this(document, bbox, null); } - PdfBoxGraphics2D(PDDocument document, PDRectangle bbox, PdfBoxGraphics2D parentGfx) + public PdfBoxGraphics2D(PDDocument document, + PDRectangle bbox, + PdfBoxGraphics2D parentGfx) + throws IOException { + this(document, createXObject(document, bbox), parentGfx); + } + + public PdfBoxGraphics2D(PDDocument document, + PDFormXObject xFormObject, + PdfBoxGraphics2D parentGfx) throws IOException { this.document = document; - this.bbox = bbox; - PDAppearanceStream appearance = new PDAppearanceStream(document); - xFormObject = appearance; - xFormObject.setResources(new PDResources()); - xFormObject.setBBox(bbox); - contentStream = new PDPageContentStream(document, appearance, + this.xFormObject = xFormObject; + this.contentStream = new PDPageContentStream(document, xFormObject, xFormObject.getStream().createOutputStream(COSName.FLATE_DECODE)); contentStreamSaveState(); if (parentGfx != null) { @@ -253,7 +258,7 @@ public class PdfBoxGraphics2D extends Graphics2D { this.paintApplier = parentGfx.paintApplier; } baseTransform = new AffineTransform(); - baseTransform.translate(0, bbox.getHeight()); + baseTransform.translate(0, xFormObject.getBBox().getHeight()); baseTransform.scale(1, -1); calcImage = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR); calcGfx = calcImage.createGraphics(); @@ -261,35 +266,58 @@ public class PdfBoxGraphics2D extends Graphics2D { copyInfo = null; } - private PdfBoxGraphics2D(PdfBoxGraphics2D gfx) throws IOException { + public PdfBoxGraphics2D(PDDocument document, + PDFormXObject xFormObject, + PDPageContentStream contentStream, + PdfBoxGraphics2D parentGfx) + throws IOException { + this.document = document; + this.xFormObject = xFormObject; + this.contentStream = contentStream; + contentStreamSaveState(); + if (parentGfx != null) { + this.colorMapper = parentGfx.colorMapper; + this.fontTextDrawer = parentGfx.fontTextDrawer; + this.imageEncoder = parentGfx.imageEncoder; + this.paintApplier = parentGfx.paintApplier; + } + baseTransform = new AffineTransform(); + baseTransform.translate(0, xFormObject.getBBox().getHeight()); + baseTransform.scale(1, -1); + calcImage = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR); + calcGfx = calcImage.createGraphics(); + font = calcGfx.getFont(); + copyInfo = null; + } + + private PdfBoxGraphics2D(PdfBoxGraphics2D pdfBoxGraphics2D) throws IOException { CopyInfo info = new CopyInfo(); info.creatingContextInfo = null; info.copy = this; - info.sourceGfx = gfx; - gfx.copyList.add(info); + info.sourceGfx = pdfBoxGraphics2D; + pdfBoxGraphics2D.copyList.add(info); this.copyInfo = info; this.hasPathOnStream = false; - this.document = gfx.document; - this.bbox = gfx.bbox; - this.xFormObject = gfx.xFormObject; - this.contentStream = gfx.contentStream; - this.baseTransform = gfx.baseTransform; - this.transform = (AffineTransform) gfx.transform.clone(); - this.calcGfx = gfx.calcGfx; - this.calcImage = gfx.calcImage; - this.font = gfx.font; - this.stroke = gfx.stroke; - this.paint = gfx.paint; - this.clipShape = gfx.clipShape; - this.backgroundColor = gfx.backgroundColor; - this.colorMapper = gfx.colorMapper; - this.fontTextDrawer = gfx.fontTextDrawer; - this.imageEncoder = gfx.imageEncoder; - this.paintApplier = gfx.paintApplier; - this.drawControl = gfx.drawControl; - this.composite = gfx.composite; - this.renderingHints = new HashMap<>(gfx.renderingHints); - this.xorColor = gfx.xorColor; + this.document = pdfBoxGraphics2D.document; + this.xFormObject = pdfBoxGraphics2D.xFormObject; + this.contentStream = pdfBoxGraphics2D.contentStream; + this.baseTransform = pdfBoxGraphics2D.baseTransform; + this.transform = (AffineTransform) pdfBoxGraphics2D.transform.clone(); + this.calcGfx = pdfBoxGraphics2D.calcGfx; + this.calcImage = pdfBoxGraphics2D.calcImage; + this.font = pdfBoxGraphics2D.font; + this.stroke = pdfBoxGraphics2D.stroke; + this.paint = pdfBoxGraphics2D.paint; + this.clipShape = pdfBoxGraphics2D.clipShape; + this.backgroundColor = pdfBoxGraphics2D.backgroundColor; + this.colorMapper = pdfBoxGraphics2D.colorMapper; + this.fontTextDrawer = pdfBoxGraphics2D.fontTextDrawer; + this.imageEncoder = pdfBoxGraphics2D.imageEncoder; + this.paintApplier = pdfBoxGraphics2D.paintApplier; + this.drawControl = pdfBoxGraphics2D.drawControl; + this.composite = pdfBoxGraphics2D.composite; + this.renderingHints = new HashMap<>(pdfBoxGraphics2D.renderingHints); + this.xorColor = pdfBoxGraphics2D.xorColor; this.saveCounter = 0; contentStreamSaveState(); } @@ -1043,7 +1071,7 @@ public class PdfBoxGraphics2D extends Graphics2D { PDTilingPattern pattern = new PDTilingPattern(); pattern.setPaintType(PDTilingPattern.PAINT_COLORED); pattern.setTilingType(PDTilingPattern.TILING_CONSTANT_SPACING_FASTER_TILING); - PDRectangle anchorRect = bbox; + PDRectangle anchorRect = xFormObject.getBBox(); pattern.setBBox(anchorRect); pattern.setXStep(anchorRect.getWidth()); pattern.setYStep(anchorRect.getHeight()); @@ -1135,9 +1163,17 @@ public class PdfBoxGraphics2D extends Graphics2D { } private void checkNoCopyActive() { - if (copyList.size() > 0) + if (copyList.size() > 0) { throw new IllegalStateException("Don't use the main context as long as a copy is active! Child context is missing a .dispose() call\n" - + gatherDebugCopyInfo(this)); + + gatherDebugCopyInfo(this)); + } + } + + private static PDFormXObject createXObject(PDDocument document, PDRectangle bbox) { + PDFormXObject xFormObject = new PDAppearanceStream(document); + xFormObject.setResources(new PDResources()); + xFormObject.setBBox(bbox); + return xFormObject; } private static String gatherDebugCopyInfo(PdfBoxGraphics2D gfx) { diff --git a/io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/DanglingGfxCaseTest.java b/io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/DanglingGfxCaseTest.java deleted file mode 100644 index a08d17c..0000000 --- a/io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/DanglingGfxCaseTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.xbib.graphics.io.pdfbox; - -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.PDPageContentStream; -import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; -import org.apache.pdfbox.util.Matrix; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.xbib.graphics.io.pdfbox.PdfBoxGraphics2D; - -import java.awt.Color; -import java.io.File; -import java.io.IOException; - -public class DanglingGfxCaseTest { - - @Test - public void testDanglingGfx() throws IOException { - - PDDocument document = new PDDocument(); - PDPage page = new PDPage(PDRectangle.A4); - document.addPage(page); - - PDPageContentStream contentStream = new PDPageContentStream(document, page); - PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(document, 400, 400); - - PdfBoxGraphics2D child = pdfBoxGraphics2D.create(10, 10, 40, 40); - child.setColor(Color.RED); - child.fillRect(0, 0, 100, 100); - - PdfBoxGraphics2D child2 = child.create(20, 20, 10, 10); - child2.setColor(Color.GREEN); - child2.drawOval(0, 0, 5, 5); - - child.create(); - - pdfBoxGraphics2D.disposeDanglingChildGraphics(); - pdfBoxGraphics2D.dispose(); - - PDFormXObject appearanceStream = pdfBoxGraphics2D.getXFormObject(); - Matrix matrix = new Matrix(); - matrix.translate(0, 20); - contentStream.transform(matrix); - contentStream.drawForm(appearanceStream); - contentStream.close(); - - File file = new File("build/test/dangling_test.pdf"); - file.getParentFile().mkdirs(); - document.save(file); - document.close(); - } - - @Test - public void testDanglingDisposeException() { - Assertions.assertThrows(IllegalStateException.class, () -> { - PDDocument document = new PDDocument(); - PDPage page = new PDPage(PDRectangle.A4); - document.addPage(page); - PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(document, 400, 400); - pdfBoxGraphics2D.create(); - pdfBoxGraphics2D.dispose(); - }); - } - - @Test - public void testDanglingDisposeException2() { - Assertions.assertThrows(IllegalStateException.class, () -> { - PDDocument document = new PDDocument(); - PDPage page = new PDPage(PDRectangle.A4); - document.addPage(page); - PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(document, 400, 400); - pdfBoxGraphics2D.create().disposeDanglingChildGraphics(); - }); - } -} diff --git a/io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/MultiPageTest.java b/io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/MultiPageTest.java index 20087bb..2ccaccf 100644 --- a/io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/MultiPageTest.java +++ b/io-pdfbox/src/test/java/org/xbib/graphics/io/pdfbox/MultiPageTest.java @@ -7,12 +7,15 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.util.Matrix; import org.jfree.chart.ChartFactory; -//import org.jfree.chart.ChartUtilities; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.labels.StandardCategoryToolTipGenerator; -import org.jfree.chart.plot.*; +import org.jfree.chart.plot.MultiplePiePlot; +import org.jfree.chart.plot.PiePlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.SpiderWebPlot; +import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.title.LegendTitle; import org.jfree.chart.title.TextTitle; @@ -28,10 +31,7 @@ import org.jfree.data.time.SimpleTimePeriod; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; -//import org.jfree.ui.RectangleEdge; -//import org.jfree.util.TableOrder; import org.junit.jupiter.api.Test; -import org.xbib.graphics.io.pdfbox.PdfBoxGraphics2D; import java.awt.Color; import java.awt.Font; @@ -46,29 +46,24 @@ public class MultiPageTest { @Test public void testMultiPageJFreeChart() throws IOException { File parentDir = new File("build/test/multipage"); - // noinspection ResultOfMethodCallIgnored parentDir.mkdirs(); File targetPDF = new File(parentDir, "multipage.pdf"); PDDocument document = new PDDocument(); for (int i = 0; i < 6; i++) { PDPage page = new PDPage(PDRectangle.A4); document.addPage(page); - PDPageContentStream contentStream = new PDPageContentStream(document, page); PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(document, 800, 400); drawOnGraphics(pdfBoxGraphics2D, i); pdfBoxGraphics2D.dispose(); - PDFormXObject appearanceStream = pdfBoxGraphics2D.getXFormObject(); Matrix matrix = new Matrix(); matrix.translate(0, 30); matrix.scale(0.7f, 1f); - contentStream.saveGraphicsState(); contentStream.transform(matrix); contentStream.drawForm(appearanceStream); contentStream.restoreGraphicsState(); - contentStream.close(); } document.save(targetPDF); diff --git a/io-vector/src/main/java/org/xbib/graphics/io/vector/VectorGraphics2D.java b/io-vector/src/main/java/org/xbib/graphics/io/vector/VectorGraphics2D.java index 488058f..a192695 100644 --- a/io-vector/src/main/java/org/xbib/graphics/io/vector/VectorGraphics2D.java +++ b/io-vector/src/main/java/org/xbib/graphics/io/vector/VectorGraphics2D.java @@ -81,6 +81,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable { private final Processor processor; private final PageSize pageSize; + /** * List of operations that were performed on this graphics object and its * derived objects. @@ -171,7 +172,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable { if ((clipNew == null || debugValidateGraphics.getClip() == null) && clipNew != debugValidateGraphics.getClip()) { throw new IllegalStateException("clip() validation failed: clip(" + clipOld + ", " + s + ") => " + clipNew + " != " + debugValidateGraphics.getClip()); } - if (clipNew != null && !equals(clipNew, debugValidateGraphics.getClip())) { + if (clipNew != null && notEquals(clipNew, debugValidateGraphics.getClip())) { throw new IllegalStateException("clip() validation failed: clip(" + clipOld + ", " + s + ") => " + clipNew + " != " + debugValidateGraphics.getClip()); } } @@ -238,7 +239,6 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable { emit(new DrawStringCommand(str, x, y)); debugValidateGraphics.drawString(str, x, y); } - } @Override @@ -744,7 +744,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable { throw new IllegalStateException("setClip() validation failed: clip=null, validation=" + debugValidateGraphics.getClip()); } - } else if (!equals(getClip(), debugValidateGraphics.getClip())) { + } else if (notEquals(getClip(), debugValidateGraphics.getClip())) { throw new IllegalStateException("setClip() validation failed: clip=" + getClip() + ", validation=" + debugValidateGraphics.getClip()); } @@ -865,11 +865,11 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable { return op.filter(bufferedImage, null); } - private static boolean equals(Shape shapeA, Shape shapeB) { + private static boolean notEquals(Shape shapeA, Shape shapeB) { PathIterator pathAIterator = shapeA.getPathIterator(null); PathIterator pathBIterator = shapeB.getPathIterator(null); if (pathAIterator.getWindingRule() != pathBIterator.getWindingRule()) { - return false; + return true; } double[] pathASegment = new double[6]; double[] pathBSegment = new double[6]; @@ -877,17 +877,17 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable { int pathASegmentType = pathAIterator.currentSegment(pathASegment); int pathBSegmentType = pathBIterator.currentSegment(pathBSegment); if (pathASegmentType != pathBSegmentType) { - return false; + return true; } for (int segmentIndex = 0; segmentIndex < pathASegment.length; segmentIndex++) { if (pathASegment[segmentIndex] != pathBSegment[segmentIndex]) { - return false; + return true; } } pathAIterator.next(); pathBIterator.next(); } - return pathBIterator.isDone(); + return !pathBIterator.isDone(); } /** diff --git a/layout-pdfbox/build.gradle b/layout-pdfbox/build.gradle index 7a11b87..4d7c572 100644 --- a/layout-pdfbox/build.gradle +++ b/layout-pdfbox/build.gradle @@ -1,3 +1,3 @@ dependencies { - implementation "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}" -} \ No newline at end of file + api "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}" +}