update to pdfbox 2.0.21, clean up pdfbox graphics io
This commit is contained in:
parent
b993f70a3d
commit
4dfde95054
9 changed files with 104 additions and 153 deletions
|
@ -25,7 +25,6 @@ ext {
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
apply from: rootProject.file('gradle/ide/idea.gradle')
|
apply from: rootProject.file('gradle/ide/idea.gradle')
|
||||||
apply from: rootProject.file('gradle/compile/java.gradle')
|
apply from: rootProject.file('gradle/compile/java.gradle')
|
||||||
apply from: rootProject.file('gradle/test/junit5.gradle')
|
apply from: rootProject.file('gradle/test/junit5.gradle')
|
||||||
|
|
|
@ -3,7 +3,7 @@ name = graphics
|
||||||
version = 3.0.0
|
version = 3.0.0
|
||||||
|
|
||||||
gradle.wrapper.version = 6.6.1
|
gradle.wrapper.version = 6.6.1
|
||||||
pdfbox.version = 2.0.19
|
pdfbox.version = 2.0.21
|
||||||
zxing.version = 3.3.1
|
zxing.version = 3.3.1
|
||||||
reflections.version = 0.9.11
|
reflections.version = 0.9.11
|
||||||
jfreechart.version = 1.5.1
|
jfreechart.version = 1.5.1
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
dependencies {
|
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.jfree:jfreechart:${project.property('jfreechart.version')}"
|
||||||
testImplementation "org.apache.xmlgraphics:batik-swing:${project.property('batik.version')}"
|
testImplementation "org.apache.xmlgraphics:batik-swing:${project.property('batik.version')}"
|
||||||
}
|
}
|
|
@ -77,7 +77,7 @@ public class DefaultPaintApplier implements PaintApplier {
|
||||||
state.nestedTransform = null;
|
state.nestedTransform = null;
|
||||||
PDShading shading = applyPaint(paint, state);
|
PDShading shading = applyPaint(paint, state);
|
||||||
if (state.pdExtendedGraphicsState != null) {
|
if (state.pdExtendedGraphicsState != null) {
|
||||||
contentStream.setGraphicsStateParameters(extGStateCache.makeUnqiue(state.pdExtendedGraphicsState));
|
contentStream.setGraphicsStateParameters(extGStateCache.makeUnique(state.pdExtendedGraphicsState));
|
||||||
}
|
}
|
||||||
return shading;
|
return shading;
|
||||||
}
|
}
|
||||||
|
@ -113,19 +113,19 @@ public class DefaultPaintApplier implements PaintApplier {
|
||||||
if (paint instanceof Color) {
|
if (paint instanceof Color) {
|
||||||
applyAsStrokingColor((Color) paint, state);
|
applyAsStrokingColor((Color) paint, state);
|
||||||
} else if (simpleName.equals("LinearGradientPaint")) {
|
} else if (simpleName.equals("LinearGradientPaint")) {
|
||||||
return shadingCache.makeUnqiue(buildLinearGradientShading(paint, state));
|
return shadingCache.makeUnique(buildLinearGradientShading(paint, state));
|
||||||
} else if (simpleName.equals("RadialGradientPaint")) {
|
} else if (simpleName.equals("RadialGradientPaint")) {
|
||||||
return shadingCache.makeUnqiue(buildRadialGradientShading(paint, state));
|
return shadingCache.makeUnique(buildRadialGradientShading(paint, state));
|
||||||
} else if (simpleName.equals("PatternPaint")) {
|
} else if (simpleName.equals("PatternPaint")) {
|
||||||
applyPatternPaint(paint, state);
|
applyPatternPaint(paint, state);
|
||||||
} else if (simpleName.equals("TilingPaint")) {
|
} else if (simpleName.equals("TilingPaint")) {
|
||||||
logger.log(Level.WARNING, "no tiling paint available");
|
logger.log(Level.WARNING, "no tiling paint available");
|
||||||
} else if (paint instanceof GradientPaint) {
|
} else if (paint instanceof GradientPaint) {
|
||||||
return shadingCache.makeUnqiue(buildGradientShading((GradientPaint) paint, state));
|
return shadingCache.makeUnique(buildGradientShading((GradientPaint) paint, state));
|
||||||
} else if (paint instanceof TexturePaint) {
|
} else if (paint instanceof TexturePaint) {
|
||||||
applyTexturePaint((TexturePaint) paint, state);
|
applyTexturePaint((TexturePaint) paint, state);
|
||||||
} else if (paint instanceof ShadingPaint) {
|
} else if (paint instanceof ShadingPaint) {
|
||||||
return shadingCache.makeUnqiue(importPDFBoxShadingPaint((ShadingPaint<?>) paint, state));
|
return shadingCache.makeUnique(importPDFBoxShadingPaint((ShadingPaint<?>) paint, state));
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.WARNING, "Don't know paint " + paint.getClass().getName());
|
logger.log(Level.WARNING, "Don't know paint " + paint.getClass().getName());
|
||||||
}
|
}
|
||||||
|
@ -148,12 +148,10 @@ public class DefaultPaintApplier implements PaintApplier {
|
||||||
PDTilingPattern pattern = new PDTilingPattern();
|
PDTilingPattern pattern = new PDTilingPattern();
|
||||||
pattern.setPaintType(PDTilingPattern.PAINT_COLORED);
|
pattern.setPaintType(PDTilingPattern.PAINT_COLORED);
|
||||||
pattern.setTilingType(PDTilingPattern.TILING_CONSTANT_SPACING_FASTER_TILING);
|
pattern.setTilingType(PDTilingPattern.TILING_CONSTANT_SPACING_FASTER_TILING);
|
||||||
|
|
||||||
pattern.setBBox(new PDRectangle((float) anchorRect.getX(), (float) anchorRect.getY(),
|
pattern.setBBox(new PDRectangle((float) anchorRect.getX(), (float) anchorRect.getY(),
|
||||||
(float) anchorRect.getWidth(), (float) anchorRect.getHeight()));
|
(float) anchorRect.getWidth(), (float) anchorRect.getHeight()));
|
||||||
pattern.setXStep((float) anchorRect.getWidth());
|
pattern.setXStep((float) anchorRect.getWidth());
|
||||||
pattern.setYStep((float) anchorRect.getHeight());
|
pattern.setYStep((float) anchorRect.getHeight());
|
||||||
|
|
||||||
AffineTransform patternTransform = new AffineTransform();
|
AffineTransform patternTransform = new AffineTransform();
|
||||||
if (paintPatternTransform != null) {
|
if (paintPatternTransform != null) {
|
||||||
paintPatternTransform = new AffineTransform(paintPatternTransform);
|
paintPatternTransform = new AffineTransform(paintPatternTransform);
|
||||||
|
@ -766,7 +764,7 @@ public class DefaultPaintApplier implements PaintApplier {
|
||||||
|
|
||||||
protected abstract int getKey(TObject obj);
|
protected abstract int getKey(TObject obj);
|
||||||
|
|
||||||
TObject makeUnqiue(TObject state) {
|
TObject makeUnique(TObject state) {
|
||||||
int key = getKey(state);
|
int key = getKey(state);
|
||||||
List<TObject> pdExtendedGraphicsStates = states.computeIfAbsent(key, k -> new ArrayList<>());
|
List<TObject> pdExtendedGraphicsStates = states.computeIfAbsent(key, k -> new ArrayList<>());
|
||||||
for (TObject s : pdExtendedGraphicsStates) {
|
for (TObject s : pdExtendedGraphicsStates) {
|
||||||
|
|
|
@ -68,10 +68,10 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class PdfBoxGraphics2D extends Graphics2D {
|
public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
|
|
||||||
private final PDFormXObject xFormObject;
|
|
||||||
|
|
||||||
private final Graphics2D calcGfx;
|
private final Graphics2D calcGfx;
|
||||||
|
|
||||||
|
private final PDFormXObject xFormObject;
|
||||||
|
|
||||||
private final PDPageContentStream contentStream;
|
private final PDPageContentStream contentStream;
|
||||||
|
|
||||||
private BufferedImage calcImage;
|
private BufferedImage calcImage;
|
||||||
|
@ -106,12 +106,10 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
|
|
||||||
private Color backgroundColor;
|
private Color backgroundColor;
|
||||||
|
|
||||||
private final CopyInfo copyInfo;
|
|
||||||
|
|
||||||
private final PDRectangle bbox;
|
|
||||||
|
|
||||||
private int saveCounter = 0;
|
private int saveCounter = 0;
|
||||||
|
|
||||||
|
private final CopyInfo copyInfo;
|
||||||
|
|
||||||
private final List<CopyInfo> copyList = new ArrayList<>();
|
private final List<CopyInfo> copyList = new ArrayList<>();
|
||||||
|
|
||||||
private final PaintApplierEnvImpl paintEnv = new PaintApplierEnvImpl();
|
private final PaintApplierEnvImpl paintEnv = new PaintApplierEnvImpl();
|
||||||
|
@ -163,9 +161,10 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
@Override
|
@Override
|
||||||
public void applyPaint(Paint paint, Shape shapeToDraw) throws IOException {
|
public void applyPaint(Paint paint, Shape shapeToDraw) throws IOException {
|
||||||
PDShading pdShading = PdfBoxGraphics2D.this.applyPaint(paint, shapeToDraw);
|
PDShading pdShading = PdfBoxGraphics2D.this.applyPaint(paint, shapeToDraw);
|
||||||
if (pdShading != null)
|
if (pdShading != null) {
|
||||||
applyShadingAsColor(pdShading);
|
applyShadingAsColor(pdShading);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FontRenderContext getFontRenderContext() {
|
public FontRenderContext getFontRenderContext() {
|
||||||
|
@ -174,7 +173,7 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PDRectangle getGraphicsBBox() {
|
public PDRectangle getGraphicsBBox() {
|
||||||
return bbox;
|
return xFormObject.getBBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -202,7 +201,8 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
* @throws IOException if something goes wrong with writing into the content stream of
|
* @throws IOException if something goes wrong with writing into the content stream of
|
||||||
* the {@link PDDocument}.
|
* 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));
|
this(document, new PDRectangle(pixelWidth, pixelHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,15 +235,20 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
this(document, bbox, null);
|
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 {
|
throws IOException {
|
||||||
this.document = document;
|
this.document = document;
|
||||||
this.bbox = bbox;
|
this.xFormObject = xFormObject;
|
||||||
PDAppearanceStream appearance = new PDAppearanceStream(document);
|
this.contentStream = new PDPageContentStream(document, xFormObject,
|
||||||
xFormObject = appearance;
|
|
||||||
xFormObject.setResources(new PDResources());
|
|
||||||
xFormObject.setBBox(bbox);
|
|
||||||
contentStream = new PDPageContentStream(document, appearance,
|
|
||||||
xFormObject.getStream().createOutputStream(COSName.FLATE_DECODE));
|
xFormObject.getStream().createOutputStream(COSName.FLATE_DECODE));
|
||||||
contentStreamSaveState();
|
contentStreamSaveState();
|
||||||
if (parentGfx != null) {
|
if (parentGfx != null) {
|
||||||
|
@ -253,7 +258,7 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
this.paintApplier = parentGfx.paintApplier;
|
this.paintApplier = parentGfx.paintApplier;
|
||||||
}
|
}
|
||||||
baseTransform = new AffineTransform();
|
baseTransform = new AffineTransform();
|
||||||
baseTransform.translate(0, bbox.getHeight());
|
baseTransform.translate(0, xFormObject.getBBox().getHeight());
|
||||||
baseTransform.scale(1, -1);
|
baseTransform.scale(1, -1);
|
||||||
calcImage = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
|
calcImage = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
|
||||||
calcGfx = calcImage.createGraphics();
|
calcGfx = calcImage.createGraphics();
|
||||||
|
@ -261,35 +266,58 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
copyInfo = null;
|
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();
|
CopyInfo info = new CopyInfo();
|
||||||
info.creatingContextInfo = null;
|
info.creatingContextInfo = null;
|
||||||
info.copy = this;
|
info.copy = this;
|
||||||
info.sourceGfx = gfx;
|
info.sourceGfx = pdfBoxGraphics2D;
|
||||||
gfx.copyList.add(info);
|
pdfBoxGraphics2D.copyList.add(info);
|
||||||
this.copyInfo = info;
|
this.copyInfo = info;
|
||||||
this.hasPathOnStream = false;
|
this.hasPathOnStream = false;
|
||||||
this.document = gfx.document;
|
this.document = pdfBoxGraphics2D.document;
|
||||||
this.bbox = gfx.bbox;
|
this.xFormObject = pdfBoxGraphics2D.xFormObject;
|
||||||
this.xFormObject = gfx.xFormObject;
|
this.contentStream = pdfBoxGraphics2D.contentStream;
|
||||||
this.contentStream = gfx.contentStream;
|
this.baseTransform = pdfBoxGraphics2D.baseTransform;
|
||||||
this.baseTransform = gfx.baseTransform;
|
this.transform = (AffineTransform) pdfBoxGraphics2D.transform.clone();
|
||||||
this.transform = (AffineTransform) gfx.transform.clone();
|
this.calcGfx = pdfBoxGraphics2D.calcGfx;
|
||||||
this.calcGfx = gfx.calcGfx;
|
this.calcImage = pdfBoxGraphics2D.calcImage;
|
||||||
this.calcImage = gfx.calcImage;
|
this.font = pdfBoxGraphics2D.font;
|
||||||
this.font = gfx.font;
|
this.stroke = pdfBoxGraphics2D.stroke;
|
||||||
this.stroke = gfx.stroke;
|
this.paint = pdfBoxGraphics2D.paint;
|
||||||
this.paint = gfx.paint;
|
this.clipShape = pdfBoxGraphics2D.clipShape;
|
||||||
this.clipShape = gfx.clipShape;
|
this.backgroundColor = pdfBoxGraphics2D.backgroundColor;
|
||||||
this.backgroundColor = gfx.backgroundColor;
|
this.colorMapper = pdfBoxGraphics2D.colorMapper;
|
||||||
this.colorMapper = gfx.colorMapper;
|
this.fontTextDrawer = pdfBoxGraphics2D.fontTextDrawer;
|
||||||
this.fontTextDrawer = gfx.fontTextDrawer;
|
this.imageEncoder = pdfBoxGraphics2D.imageEncoder;
|
||||||
this.imageEncoder = gfx.imageEncoder;
|
this.paintApplier = pdfBoxGraphics2D.paintApplier;
|
||||||
this.paintApplier = gfx.paintApplier;
|
this.drawControl = pdfBoxGraphics2D.drawControl;
|
||||||
this.drawControl = gfx.drawControl;
|
this.composite = pdfBoxGraphics2D.composite;
|
||||||
this.composite = gfx.composite;
|
this.renderingHints = new HashMap<>(pdfBoxGraphics2D.renderingHints);
|
||||||
this.renderingHints = new HashMap<>(gfx.renderingHints);
|
this.xorColor = pdfBoxGraphics2D.xorColor;
|
||||||
this.xorColor = gfx.xorColor;
|
|
||||||
this.saveCounter = 0;
|
this.saveCounter = 0;
|
||||||
contentStreamSaveState();
|
contentStreamSaveState();
|
||||||
}
|
}
|
||||||
|
@ -1043,7 +1071,7 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
PDTilingPattern pattern = new PDTilingPattern();
|
PDTilingPattern pattern = new PDTilingPattern();
|
||||||
pattern.setPaintType(PDTilingPattern.PAINT_COLORED);
|
pattern.setPaintType(PDTilingPattern.PAINT_COLORED);
|
||||||
pattern.setTilingType(PDTilingPattern.TILING_CONSTANT_SPACING_FASTER_TILING);
|
pattern.setTilingType(PDTilingPattern.TILING_CONSTANT_SPACING_FASTER_TILING);
|
||||||
PDRectangle anchorRect = bbox;
|
PDRectangle anchorRect = xFormObject.getBBox();
|
||||||
pattern.setBBox(anchorRect);
|
pattern.setBBox(anchorRect);
|
||||||
pattern.setXStep(anchorRect.getWidth());
|
pattern.setXStep(anchorRect.getWidth());
|
||||||
pattern.setYStep(anchorRect.getHeight());
|
pattern.setYStep(anchorRect.getHeight());
|
||||||
|
@ -1135,10 +1163,18 @@ public class PdfBoxGraphics2D extends Graphics2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkNoCopyActive() {
|
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"
|
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) {
|
private static String gatherDebugCopyInfo(PdfBoxGraphics2D gfx) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,12 +7,15 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||||
import org.apache.pdfbox.util.Matrix;
|
import org.apache.pdfbox.util.Matrix;
|
||||||
import org.jfree.chart.ChartFactory;
|
import org.jfree.chart.ChartFactory;
|
||||||
//import org.jfree.chart.ChartUtilities;
|
|
||||||
import org.jfree.chart.ChartUtils;
|
import org.jfree.chart.ChartUtils;
|
||||||
import org.jfree.chart.JFreeChart;
|
import org.jfree.chart.JFreeChart;
|
||||||
import org.jfree.chart.axis.NumberAxis;
|
import org.jfree.chart.axis.NumberAxis;
|
||||||
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
|
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.renderer.xy.XYLineAndShapeRenderer;
|
||||||
import org.jfree.chart.title.LegendTitle;
|
import org.jfree.chart.title.LegendTitle;
|
||||||
import org.jfree.chart.title.TextTitle;
|
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.XYDataset;
|
||||||
import org.jfree.data.xy.XYSeries;
|
import org.jfree.data.xy.XYSeries;
|
||||||
import org.jfree.data.xy.XYSeriesCollection;
|
import org.jfree.data.xy.XYSeriesCollection;
|
||||||
//import org.jfree.ui.RectangleEdge;
|
|
||||||
//import org.jfree.util.TableOrder;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.xbib.graphics.io.pdfbox.PdfBoxGraphics2D;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
@ -46,29 +46,24 @@ public class MultiPageTest {
|
||||||
@Test
|
@Test
|
||||||
public void testMultiPageJFreeChart() throws IOException {
|
public void testMultiPageJFreeChart() throws IOException {
|
||||||
File parentDir = new File("build/test/multipage");
|
File parentDir = new File("build/test/multipage");
|
||||||
// noinspection ResultOfMethodCallIgnored
|
|
||||||
parentDir.mkdirs();
|
parentDir.mkdirs();
|
||||||
File targetPDF = new File(parentDir, "multipage.pdf");
|
File targetPDF = new File(parentDir, "multipage.pdf");
|
||||||
PDDocument document = new PDDocument();
|
PDDocument document = new PDDocument();
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
PDPage page = new PDPage(PDRectangle.A4);
|
PDPage page = new PDPage(PDRectangle.A4);
|
||||||
document.addPage(page);
|
document.addPage(page);
|
||||||
|
|
||||||
PDPageContentStream contentStream = new PDPageContentStream(document, page);
|
PDPageContentStream contentStream = new PDPageContentStream(document, page);
|
||||||
PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(document, 800, 400);
|
PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(document, 800, 400);
|
||||||
drawOnGraphics(pdfBoxGraphics2D, i);
|
drawOnGraphics(pdfBoxGraphics2D, i);
|
||||||
pdfBoxGraphics2D.dispose();
|
pdfBoxGraphics2D.dispose();
|
||||||
|
|
||||||
PDFormXObject appearanceStream = pdfBoxGraphics2D.getXFormObject();
|
PDFormXObject appearanceStream = pdfBoxGraphics2D.getXFormObject();
|
||||||
Matrix matrix = new Matrix();
|
Matrix matrix = new Matrix();
|
||||||
matrix.translate(0, 30);
|
matrix.translate(0, 30);
|
||||||
matrix.scale(0.7f, 1f);
|
matrix.scale(0.7f, 1f);
|
||||||
|
|
||||||
contentStream.saveGraphicsState();
|
contentStream.saveGraphicsState();
|
||||||
contentStream.transform(matrix);
|
contentStream.transform(matrix);
|
||||||
contentStream.drawForm(appearanceStream);
|
contentStream.drawForm(appearanceStream);
|
||||||
contentStream.restoreGraphicsState();
|
contentStream.restoreGraphicsState();
|
||||||
|
|
||||||
contentStream.close();
|
contentStream.close();
|
||||||
}
|
}
|
||||||
document.save(targetPDF);
|
document.save(targetPDF);
|
||||||
|
|
|
@ -81,6 +81,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
private final Processor processor;
|
private final Processor processor;
|
||||||
|
|
||||||
private final PageSize pageSize;
|
private final PageSize pageSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of operations that were performed on this graphics object and its
|
* List of operations that were performed on this graphics object and its
|
||||||
* derived objects.
|
* derived objects.
|
||||||
|
@ -171,7 +172,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
if ((clipNew == null || debugValidateGraphics.getClip() == null) && clipNew != debugValidateGraphics.getClip()) {
|
if ((clipNew == null || debugValidateGraphics.getClip() == null) && clipNew != debugValidateGraphics.getClip()) {
|
||||||
throw new IllegalStateException("clip() validation failed: clip(" + clipOld + ", " + s + ") => " + 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());
|
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));
|
emit(new DrawStringCommand(str, x, y));
|
||||||
debugValidateGraphics.drawString(str, x, y);
|
debugValidateGraphics.drawString(str, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -744,7 +744,7 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
throw new IllegalStateException("setClip() validation failed: clip=null, validation=" +
|
throw new IllegalStateException("setClip() validation failed: clip=null, validation=" +
|
||||||
debugValidateGraphics.getClip());
|
debugValidateGraphics.getClip());
|
||||||
}
|
}
|
||||||
} else if (!equals(getClip(), debugValidateGraphics.getClip())) {
|
} else if (notEquals(getClip(), debugValidateGraphics.getClip())) {
|
||||||
throw new IllegalStateException("setClip() validation failed: clip=" + getClip() + ", validation=" +
|
throw new IllegalStateException("setClip() validation failed: clip=" + getClip() + ", validation=" +
|
||||||
debugValidateGraphics.getClip());
|
debugValidateGraphics.getClip());
|
||||||
}
|
}
|
||||||
|
@ -865,11 +865,11 @@ public class VectorGraphics2D extends Graphics2D implements Cloneable {
|
||||||
return op.filter(bufferedImage, null);
|
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 pathAIterator = shapeA.getPathIterator(null);
|
||||||
PathIterator pathBIterator = shapeB.getPathIterator(null);
|
PathIterator pathBIterator = shapeB.getPathIterator(null);
|
||||||
if (pathAIterator.getWindingRule() != pathBIterator.getWindingRule()) {
|
if (pathAIterator.getWindingRule() != pathBIterator.getWindingRule()) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
double[] pathASegment = new double[6];
|
double[] pathASegment = new double[6];
|
||||||
double[] pathBSegment = 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 pathASegmentType = pathAIterator.currentSegment(pathASegment);
|
||||||
int pathBSegmentType = pathBIterator.currentSegment(pathBSegment);
|
int pathBSegmentType = pathBIterator.currentSegment(pathBSegment);
|
||||||
if (pathASegmentType != pathBSegmentType) {
|
if (pathASegmentType != pathBSegmentType) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
for (int segmentIndex = 0; segmentIndex < pathASegment.length; segmentIndex++) {
|
for (int segmentIndex = 0; segmentIndex < pathASegment.length; segmentIndex++) {
|
||||||
if (pathASegment[segmentIndex] != pathBSegment[segmentIndex]) {
|
if (pathASegment[segmentIndex] != pathBSegment[segmentIndex]) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pathAIterator.next();
|
pathAIterator.next();
|
||||||
pathBIterator.next();
|
pathBIterator.next();
|
||||||
}
|
}
|
||||||
return pathBIterator.isDone();
|
return !pathBIterator.isDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}"
|
api "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}"
|
||||||
}
|
}
|
Loading…
Reference in a new issue