update to pdfbox 2.0.21, clean up pdfbox graphics io

This commit is contained in:
Jörg Prante 2020-11-10 09:32:04 +01:00
parent b993f70a3d
commit 4dfde95054
9 changed files with 104 additions and 153 deletions

View file

@ -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')

View file

@ -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

View file

@ -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')}"
} }

View file

@ -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) {

View file

@ -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,8 +161,9 @@ 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
@ -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,9 +1163,17 @@ 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) {

View file

@ -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();
});
}
}

View file

@ -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);

View file

@ -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();
} }
/** /**

View file

@ -1,3 +1,3 @@
dependencies { dependencies {
implementation "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}" api "org.apache.pdfbox:pdfbox:${project.property('pdfbox.version')}"
} }