From 4ddee64d14574ff888d433b861d0dd7f37bd51e4 Mon Sep 17 00:00:00 2001 From: "valery.bokov" Date: Thu, 16 Apr 2026 22:30:14 +0200 Subject: [PATCH 1/2] reset graphics state in PDFPrintable.print method --- .../apache/pdfbox/printing/PDFPrintable.java | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java b/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java index 8926024ac7a..b1ec168f11a 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java @@ -22,6 +22,8 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.print.PageFormat; @@ -308,12 +310,27 @@ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) // Drawing after the blit avoids losing the thin stroke during raster scale-down. if (showPageBorder) { - printerGraphics.setTransform(printerBorderTransform); - printerGraphics.setClip(0, 0, (int) imageableWidth, (int) imageableHeight); - printerGraphics.scale(borderScale, borderScale); - printerGraphics.setColor(Color.GRAY); - printerGraphics.setStroke(new BasicStroke(0.5f)); - printerGraphics.drawRect(0, 0, (int) cropBox.getWidth(), (int) cropBox.getHeight()); + // save state so transform/clip/color/stroke changes don't leak back to the caller + AffineTransform savedTransform = printerGraphics.getTransform(); + Shape savedClip = printerGraphics.getClip(); + Color savedColor = printerGraphics.getColor(); + Stroke savedStroke = printerGraphics.getStroke(); + try + { + printerGraphics.setTransform(printerBorderTransform); + printerGraphics.setClip(0, 0, (int) imageableWidth, (int) imageableHeight); + printerGraphics.scale(borderScale, borderScale); + printerGraphics.setColor(Color.GRAY); + printerGraphics.setStroke(new BasicStroke(0.5f)); + printerGraphics.drawRect(0, 0, (int) cropBox.getWidth(), (int) cropBox.getHeight()); + } + finally + { + printerGraphics.setTransform(savedTransform); + printerGraphics.setClip(savedClip); + printerGraphics.setColor(savedColor); + printerGraphics.setStroke(savedStroke); + } } return PAGE_EXISTS; From 3af066816b9e4d3487db2dff921a6702c2e38e39 Mon Sep 17 00:00:00 2001 From: "valery.bokov" Date: Fri, 17 Apr 2026 19:07:49 +0200 Subject: [PATCH 2/2] reset transform in PDFPrintable.print method --- .../apache/pdfbox/printing/PDFPrintable.java | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java b/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java index b1ec168f11a..84a8819620e 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/printing/PDFPrintable.java @@ -210,11 +210,21 @@ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) Graphics2D printerGraphics = null; Graphics2D graphics2D = null; + AffineTransform callerTransform = null; + Shape callerClip = null; + Color callerColor = null; + Color callerBackground = null; + Stroke callerStroke = null; try { printerGraphics = (Graphics2D) graphics; graphics2D = printerGraphics; + callerTransform = printerGraphics.getTransform(); + callerClip = printerGraphics.getClip(); + callerColor = printerGraphics.getColor(); + callerBackground = printerGraphics.getBackground(); + callerStroke = printerGraphics.getStroke(); // capture the DPI that will be used for rasterizing the image // if rasterizing is specified @@ -310,27 +320,12 @@ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) // Drawing after the blit avoids losing the thin stroke during raster scale-down. if (showPageBorder) { - // save state so transform/clip/color/stroke changes don't leak back to the caller - AffineTransform savedTransform = printerGraphics.getTransform(); - Shape savedClip = printerGraphics.getClip(); - Color savedColor = printerGraphics.getColor(); - Stroke savedStroke = printerGraphics.getStroke(); - try - { - printerGraphics.setTransform(printerBorderTransform); - printerGraphics.setClip(0, 0, (int) imageableWidth, (int) imageableHeight); - printerGraphics.scale(borderScale, borderScale); - printerGraphics.setColor(Color.GRAY); - printerGraphics.setStroke(new BasicStroke(0.5f)); - printerGraphics.drawRect(0, 0, (int) cropBox.getWidth(), (int) cropBox.getHeight()); - } - finally - { - printerGraphics.setTransform(savedTransform); - printerGraphics.setClip(savedClip); - printerGraphics.setColor(savedColor); - printerGraphics.setStroke(savedStroke); - } + printerGraphics.setTransform(printerBorderTransform); + printerGraphics.setClip(0, 0, (int) imageableWidth, (int) imageableHeight); + printerGraphics.scale(borderScale, borderScale); + printerGraphics.setColor(Color.GRAY); + printerGraphics.setStroke(new BasicStroke(0.5f)); + printerGraphics.drawRect(0, 0, (int) cropBox.getWidth(), (int) cropBox.getHeight()); } return PAGE_EXISTS; @@ -341,6 +336,16 @@ public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) } finally { + // restore caller's state (guarded because the cast on line above may have thrown + // before any state was captured) + if (printerGraphics != null && callerTransform != null) + { + printerGraphics.setTransform(callerTransform); + printerGraphics.setClip(callerClip); + printerGraphics.setColor(callerColor); + printerGraphics.setBackground(callerBackground); + printerGraphics.setStroke(callerStroke); + } if (graphics2D != null && graphics2D != printerGraphics) { graphics2D.dispose();