Skip to content

Commit fdb00f3

Browse files
committed
PDFBOX-6049: introduce new adjustRotation option
git-svn-id: https://svn.apache.org/repos/asf/pdfbox/trunk@1927718 13f79535-47bb-0310-9956-ffa450edef68
1 parent 5f5fd46 commit fdb00f3

File tree

2 files changed

+54
-7
lines changed

2 files changed

+54
-7
lines changed

pdfbox/src/main/java/org/apache/pdfbox/multipdf/Overlay.java

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public enum Position
6767
}
6868

6969
private LayoutPage defaultOverlayPage;
70+
private final Map<Integer,LayoutPage> rotatedDefaultOverlayPagesMap = new HashMap<>();
7071
private LayoutPage firstPageOverlayPage;
7172
private LayoutPage lastPageOverlayPage;
7273
private LayoutPage oddPageOverlayPage;
@@ -100,6 +101,7 @@ public enum Position
100101

101102
private int numberOfOverlayPages = 0;
102103
private boolean useAllOverlayPages = false;
104+
private boolean adjustRotation = false;
103105

104106
/**
105107
* This will add overlays to a document.
@@ -204,6 +206,7 @@ public void close() throws IOException
204206
}
205207
openDocumentsSet.clear();
206208
specificPageOverlayLayoutPageMap.clear();
209+
rotatedDefaultOverlayPagesMap.clear();
207210
}
208211

209212
private void loadPDFs() throws IOException
@@ -288,9 +291,9 @@ private static final class LayoutPage
288291
private final PDRectangle overlayMediaBox;
289292
private final COSStream overlayCOSStream;
290293
private final COSDictionary overlayResources;
291-
private final short overlayRotation;
294+
private int overlayRotation;
292295

293-
private LayoutPage(PDRectangle mediaBox, COSStream contentStream, COSDictionary resources, short rotation)
296+
private LayoutPage(PDRectangle mediaBox, COSStream contentStream, COSDictionary resources, int rotation)
294297
{
295298
overlayMediaBox = mediaBox;
296299
overlayCOSStream = contentStream;
@@ -326,7 +329,7 @@ private LayoutPage createLayoutPage(PDPage page) throws IOException
326329
resources = new PDResources();
327330
}
328331
return new LayoutPage(page.getMediaBox(), createCombinedContentStream(contents),
329-
resources.getCOSObject(), (short) page.getRotation());
332+
resources.getCOSObject(), page.getRotation());
330333
}
331334

332335
private Map<Integer,LayoutPage> createPageOverlayLayoutPageMap(PDDocument doc) throws IOException
@@ -468,7 +471,7 @@ private void overlayPage(PDPage page, LayoutPage layoutPage, COSArray array,
468471
array.add(createOverlayStream(page, layoutPage, formXObjectId));
469472
}
470473

471-
private LayoutPage getLayoutPage(int pageNumber, int numberOfPages)
474+
private LayoutPage getLayoutPage(int pageNumber, int numberOfPages) throws IOException
472475
{
473476
LayoutPage layoutPage = null;
474477
if (!useAllOverlayPages && specificPageOverlayLayoutPageMap.containsKey(pageNumber))
@@ -494,6 +497,27 @@ else if ((pageNumber % 2 == 0) && (evenPageOverlayPage != null))
494497
else if (defaultOverlayPage != null)
495498
{
496499
layoutPage = defaultOverlayPage;
500+
501+
if (adjustRotation)
502+
{
503+
// PDFBOX-6049: consider the rotation of the document page
504+
// Note that this segment is only the second best solution to the problem. The best
505+
// would be to make appropriate transforms in calculateAffineTransform()
506+
PDPage page = inputPDFDocument.getPage(pageNumber - 1);
507+
if (page.getRotation() != 0)
508+
{
509+
LayoutPage rotatedLayoutPage = rotatedDefaultOverlayPagesMap.get(page.getRotation());
510+
if (rotatedLayoutPage == null)
511+
{
512+
// createLayoutPage must be called because we can't reuse the COSStream
513+
rotatedLayoutPage = createLayoutPage(defaultOverlayDocument.getPage(0));
514+
int newRotation = (rotatedLayoutPage.overlayRotation - page.getRotation() + 360) % 360;
515+
rotatedLayoutPage.overlayRotation = newRotation;
516+
rotatedDefaultOverlayPagesMap.put(page.getRotation(), rotatedLayoutPage);
517+
}
518+
return rotatedLayoutPage;
519+
}
520+
}
497521
}
498522
else if (useAllOverlayPages)
499523
{
@@ -516,15 +540,15 @@ private PDFormXObject createOverlayFormXObject(LayoutPage layoutPage, PDFCloneUt
516540
{
517541
case 90:
518542
at.translate(0, layoutPage.overlayMediaBox.getWidth());
519-
at.rotate(Math.toRadians(-90));
543+
at.quadrantRotate(3); // 270
520544
break;
521545
case 180:
522546
at.translate(layoutPage.overlayMediaBox.getWidth(), layoutPage.overlayMediaBox.getHeight());
523-
at.rotate(Math.toRadians(-180));
547+
at.quadrantRotate(2); // 180
524548
break;
525549
case 270:
526550
at.translate(layoutPage.overlayMediaBox.getHeight(), 0);
527-
at.rotate(Math.toRadians(-270));
551+
at.quadrantRotate(1); // 90
528552
break;
529553
default:
530554
break;
@@ -795,4 +819,23 @@ public void setEvenPageOverlayPDF(PDDocument evenPageOverlayPDF)
795819
{
796820
evenPageOverlayDocument = evenPageOverlayPDF;
797821
}
822+
823+
/**
824+
* This sets whether the overlay is to be rotated according to the rotation of the pages of the
825+
* source document. This may look weird if the content of the document is also rotated. So it's
826+
* really a users decision to activate this option if the overlay appears rotated in some pages
827+
* of the result document and this isn't wanted.
828+
* <p>
829+
* This setting will only apply to usage of the default overlay, because it is assumed that when
830+
* using specific overlays for specific pages, it is known in advance what kind of input there
831+
* is.
832+
*
833+
* @param adjustRotation if true, the overlay will always look the same when the result file is
834+
* displayed on the screen. If false (default) then it will be rotated if the page is rotated.
835+
*/
836+
public void setAdjustRotation(boolean adjustRotation)
837+
{
838+
this.adjustRotation = adjustRotation;
839+
840+
}
798841
}

tools/src/main/java/org/apache/pdfbox/tools/OverlayPDF.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public final class OverlayPDF implements Callable<Integer>
6060
@Option(names = "-useAllPages", description = "overlay file used for overlay, all pages are used by simply repeating them")
6161
private File useAllPages;
6262

63+
@Option(names = "-adjustRotation", description = "adjust rotation for rotated source pages (applies only if default overlay file is used)")
64+
private boolean adjustRotation = false;
65+
6366
@Option(names = "-page", description = "overlay file used for the given page number, may occur more than once")
6467
Map<Integer, String> specificPageOverlayFile = new HashMap<>();
6568

@@ -140,6 +143,7 @@ public Integer call()
140143
{
141144
overlayer.setInputFile(infile.getAbsolutePath());
142145
}
146+
overlayer.setAdjustRotation(adjustRotation);
143147

144148

145149
try (PDDocument result = overlayer.overlay(specificPageOverlayFile))

0 commit comments

Comments
 (0)