Author: tilman
Date: Tue Aug 12 18:50:21 2025
New Revision: 1927773
Log:
PDFBOX-6049: introduce new adjustRotation option
Modified:
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Overlay.java
pdfbox/branches/2.0/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java
Modified:
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Overlay.java
==============================================================================
---
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Overlay.java
Tue Aug 12 18:45:02 2025 (r1927772)
+++
pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/Overlay.java
Tue Aug 12 18:50:21 2025 (r1927773)
@@ -30,6 +30,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
@@ -53,6 +55,8 @@ import org.apache.pdfbox.pdmodel.graphic
*/
public class Overlay implements Closeable
{
+ private static final Log LOG = LogFactory.getLog(Overlay.class);
+
/**
* Possible location of the overlaid pages: foreground or background.
*/
@@ -62,6 +66,7 @@ public class Overlay implements Closeabl
}
private LayoutPage defaultOverlayPage;
+ private final Map<Integer,LayoutPage> rotatedDefaultOverlayPagesMap = new
HashMap<Integer, LayoutPage>();
private LayoutPage firstPageOverlayPage;
private LayoutPage lastPageOverlayPage;
private LayoutPage oddPageOverlayPage;
@@ -95,6 +100,7 @@ public class Overlay implements Closeabl
private int numberOfOverlayPages = 0;
private boolean useAllOverlayPages = false;
+ private boolean adjustRotation = false;
/**
* This will add overlays to a document.
@@ -199,6 +205,7 @@ public class Overlay implements Closeabl
}
openDocumentsSet.clear();
specificPageOverlayLayoutPageMap.clear();
+ rotatedDefaultOverlayPagesMap.clear();
}
private void loadPDFs() throws IOException
@@ -283,7 +290,7 @@ public class Overlay implements Closeabl
private final PDRectangle overlayMediaBox;
private final COSStream overlayCOSStream;
private final COSDictionary overlayResources;
- private final int overlayRotation;
+ private int overlayRotation;
private LayoutPage(PDRectangle mediaBox, COSStream contentStream,
COSDictionary resources, int rotation)
{
@@ -387,6 +394,7 @@ public class Overlay implements Closeabl
private void processPages(PDDocument document) throws IOException
{
int pageCounter = 0;
+ PDFCloneUtility cloner = new PDFCloneUtility(document);
PDPageTree pageTree = document.getPages();
int numberOfPages = pageTree.getCount();
for (PDPage page : pageTree)
@@ -459,7 +467,7 @@ public class Overlay implements Closeabl
array.add(createOverlayStream(page, layoutPage, formXObjectId));
}
- private LayoutPage getLayoutPage(int pageNumber, int numberOfPages)
+ private LayoutPage getLayoutPage(int pageNumber, int numberOfPages) throws
IOException
{
LayoutPage layoutPage = null;
if (!useAllOverlayPages &&
specificPageOverlayLayoutPageMap.containsKey(pageNumber))
@@ -485,6 +493,18 @@ public class Overlay implements Closeabl
else if (defaultOverlayPage != null)
{
layoutPage = defaultOverlayPage;
+
+ if (adjustRotation)
+ {
+ // PDFBOX-6049: consider the rotation of the document page
+ // Note that this segment is only the second best solution to
the problem. The best
+ // would be to make appropriate transforms in
calculateAffineTransform()
+ PDPage page = inputPDFDocument.getPage(pageNumber - 1);
+ if (page.getRotation() != 0)
+ {
+ return createAdjustedLayoutPage(page);
+ }
+ }
}
else if (useAllOverlayPages)
{
@@ -494,7 +514,21 @@ public class Overlay implements Closeabl
return layoutPage;
}
- private PDFormXObject createOverlayFormXObject(LayoutPage layoutPage)
+ private LayoutPage createAdjustedLayoutPage(PDPage page) throws IOException
+ {
+ LayoutPage rotatedLayoutPage =
rotatedDefaultOverlayPagesMap.get(page.getRotation());
+ if (rotatedLayoutPage == null)
+ {
+ // createLayoutPage must be called because we can't reuse the
COSStream
+ rotatedLayoutPage =
createLayoutPage(defaultOverlayDocument.getPage(0));
+ int newRotation = (rotatedLayoutPage.overlayRotation -
page.getRotation() + 360) % 360;
+ rotatedLayoutPage.overlayRotation = newRotation;
+ rotatedDefaultOverlayPagesMap.put(page.getRotation(),
rotatedLayoutPage);
+ }
+ return rotatedLayoutPage;
+ }
+
+ private PDFormXObject createOverlayFormXObject(LayoutPage layoutPage)
throws IOException
{
PDFormXObject xobjForm = new
PDFormXObject(layoutPage.overlayCOSStream);
xobjForm.setResources(new PDResources(layoutPage.overlayResources));
@@ -572,6 +606,10 @@ public class Overlay implements Closeabl
PDRectangle pageMediaBox = page.getMediaBox();
float hShift = (pageMediaBox.getWidth() - overlayMediaBox.getWidth())
/ 2.0f;
float vShift = (pageMediaBox.getHeight() -
overlayMediaBox.getHeight()) / 2.0f;
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("Overlay position: (" + hShift + "," + vShift + ")");
+ }
at.translate(hShift, vShift);
return at;
}
@@ -782,4 +820,22 @@ public class Overlay implements Closeabl
{
evenPageOverlayDocument = evenPageOverlayPDF;
}
+
+ /**
+ * This sets whether the overlay is to be rotated according to the
rotation of the pages of the
+ * source document. This may look weird if the content of the document is
also rotated. So it's
+ * really a users decision to activate this option if the overlay appears
rotated in some pages
+ * of the result document and this isn't wanted.
+ * <p>
+ * This setting will only apply to usage of the default overlay, because
it is assumed that when
+ * using specific overlays for specific pages, it is known in advance what
kind of input there
+ * is.
+ *
+ * @param adjustRotation if true, the overlay will always look the same
when the result file is
+ * displayed on the screen. If false (default) then it will be rotated if
the page is rotated.
+ */
+ public void setAdjustRotation(boolean adjustRotation)
+ {
+ this.adjustRotation = adjustRotation;
+ }
}
Modified:
pdfbox/branches/2.0/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java
==============================================================================
---
pdfbox/branches/2.0/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java
Tue Aug 12 18:45:02 2025 (r1927772)
+++
pdfbox/branches/2.0/tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java
Tue Aug 12 18:50:21 2025 (r1927773)
@@ -45,6 +45,7 @@ public final class OverlayPDF
private static final String LAST = "-last";
private static final String PAGE = "-page";
private static final String USEALLPAGES = "-useAllPages";
+ private static final String ADJUSTROTATION = "-adjustRotation";
private OverlayPDF()
{
@@ -122,10 +123,14 @@ public final class OverlayPDF
specificPageOverlayFile.put(Integer.parseInt(args[i +
1].trim()), args[i + 2].trim());
i += 2;
}
+ else if (arg.equals(ADJUSTROTATION))
+ {
+ overlayer.setAdjustRotation(true);
+ }
else if (overlayer.getDefaultOverlayFile() == null)
{
overlayer.setDefaultOverlayFile(arg);
- }
+ }
else
{
usage();