Skip to content

Commit 1b44f24

Browse files
Fix ignorePageRotationForContent flag
1 parent 9b9a11b commit 1b44f24

File tree

2 files changed

+72
-34
lines changed

2 files changed

+72
-34
lines changed

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfPage.java

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,15 @@ public class PdfPage extends PdfObjectWrapper<PdfDictionary> {
8585
// TODO This key contains reference to all articles, while this articles could reference to lots of pages.
8686
// See DEVSIX-191
8787
PdfName.B));
88+
8889
/**
8990
* Automatically rotate new content if the page has a rotation ( is disabled by default )
9091
*/
91-
private boolean ignoreContentRotation = true;
92+
private boolean ignorePageRotationForContent = false;
93+
/**
94+
* See {@link #isPageRotationInverseMatrixWritten()}.
95+
*/
96+
private boolean pageRotationInverseMatrixWritten = false;
9297

9398
protected PdfPage(PdfDictionary pdfObject) {
9499
super(pdfObject);
@@ -158,8 +163,9 @@ public int getRotation() {
158163
}
159164
}
160165

161-
public void setRotation(int degAngle) {
166+
public PdfPage setRotation(int degAngle) {
162167
getPdfObject().put(PdfName.Rotate, new PdfNumber(degAngle));
168+
return this;
163169
}
164170

165171
public PdfStream getContentStream(int index) {
@@ -232,9 +238,10 @@ public PdfResources getResources() {
232238
return this.resources;
233239
}
234240

235-
public void setResources(PdfResources pdfResources) {
241+
public PdfPage setResources(PdfResources pdfResources) {
236242
getPdfObject().put(PdfName.Resources, pdfResources.getPdfObject());
237243
this.resources = pdfResources;
244+
return this;
238245
}
239246

240247

@@ -416,8 +423,9 @@ public Rectangle getMediaBox() {
416423
return mediaBox.toRectangle();
417424
}
418425

419-
public void setMediaBox(Rectangle rectangle) {
426+
public PdfPage setMediaBox(Rectangle rectangle) {
420427
getPdfObject().put(PdfName.MediaBox, new PdfArray(rectangle));
428+
return this;
421429
}
422430

423431

@@ -433,30 +441,33 @@ public Rectangle getCropBox() {
433441
return cropBox.toRectangle();
434442
}
435443

436-
public void setCropBox(Rectangle rectangle) {
444+
public PdfPage setCropBox(Rectangle rectangle) {
437445
getPdfObject().put(PdfName.CropBox, new PdfArray(rectangle));
446+
return this;
438447
}
439448

440-
public void setArtBox(Rectangle rectangle) {
449+
public PdfPage setArtBox(Rectangle rectangle) {
441450
if (getPdfObject().getAsRectangle(PdfName.TrimBox) != null) {
442451
getPdfObject().remove(PdfName.TrimBox);
443452
Logger logger = LoggerFactory.getLogger(PdfPage.class);
444453
logger.warn(LogMessageConstant.ONLY_ONE_OF_ARTBOX_OR_TRIMBOX_CAN_EXIST_IN_THE_PAGE);
445454
}
446455
getPdfObject().put(PdfName.ArtBox, new PdfArray(rectangle));
456+
return this;
447457
}
448458

449459
public Rectangle getArtBox() {
450460
return getPdfObject().getAsRectangle(PdfName.ArtBox);
451461
}
452462

453-
public void setTrimBox(Rectangle rectangle) {
463+
public PdfPage setTrimBox(Rectangle rectangle) {
454464
if (getPdfObject().getAsRectangle(PdfName.ArtBox) != null) {
455465
getPdfObject().remove(PdfName.ArtBox);
456466
Logger logger = LoggerFactory.getLogger(PdfPage.class);
457467
logger.warn(LogMessageConstant.ONLY_ONE_OF_ARTBOX_OR_TRIMBOX_CAN_EXIST_IN_THE_PAGE);
458468
}
459469
getPdfObject().put(PdfName.TrimBox, new PdfArray(rectangle));
470+
return this;
460471
}
461472

462473
public Rectangle getTrimBox() {
@@ -634,18 +645,19 @@ public List<PdfOutline> getOutlines(boolean updateOutlines) {
634645
* @return true - if in case the page has a rotation, then new content will be automatically rotated in the
635646
* opposite direction. On the rotated page this would look like if new content ignores page rotation.
636647
*/
637-
public boolean isIgnoreContentRotation() {
638-
return ignoreContentRotation;
648+
public boolean isIgnorePageRotationForContent() {
649+
return ignorePageRotationForContent;
639650
}
640651

641652
/**
642653
* If true - defines that in case the page has a rotation, then new content will be automatically rotated in the
643654
* opposite direction. On the rotated page this would look like if new content ignores page rotation.
644655
* Default value - {@code false}.
645-
* @param ignoreContentRotation - true to ignore rotation of the new content on the rotated page.
656+
* @param ignorePageRotationForContent - true to ignore rotation of the new content on the rotated page.
646657
*/
647-
public void setIgnoreContentRotation(boolean ignoreContentRotation) {
648-
this.ignoreContentRotation = ignoreContentRotation;
658+
public PdfPage setIgnorePageRotationForContent(boolean ignorePageRotationForContent) {
659+
this.ignorePageRotationForContent = ignorePageRotationForContent;
660+
return this;
649661
}
650662

651663
/**
@@ -708,6 +720,31 @@ public PdfPage put(PdfName key, PdfObject value) {
708720
return this;
709721
}
710722

723+
/**
724+
* This flag is meaningful for the case, when page rotation is applied and ignorePageRotationForContent
725+
* is set to true. NOTE: It is needed for the internal usage.
726+
* <br/><br/>
727+
* This flag defines if inverse matrix (which rotates content into the opposite direction from page rotation
728+
* direction in order to give the impression of the not rotated text) is already applied to the page content stream.
729+
* See {@link #setIgnorePageRotationForContent(boolean)}
730+
* @return true, if inverse matrix is already applied, false otherwise.
731+
*/
732+
public boolean isPageRotationInverseMatrixWritten() {
733+
return pageRotationInverseMatrixWritten;
734+
}
735+
736+
/**
737+
* NOTE: For internal usage! Use this method only if you know what you are doing.
738+
* <br/><br/>
739+
* This method is called when inverse matrix (which rotates content into the opposite direction from page rotation
740+
* direction in order to give the impression of the not rotated text) is applied to the page content stream.
741+
* See {@link #setIgnorePageRotationForContent(boolean)}
742+
*/
743+
public void setPageRotationInverseMatrixWritten() {
744+
// this method specifically return void to discourage it's unintended usage
745+
pageRotationInverseMatrixWritten = true;
746+
}
747+
711748
@Override
712749
protected boolean isWrappedObjectMustBeIndirect() {
713750
return true;

kernel/src/main/java/com/itextpdf/kernel/pdf/canvas/PdfCanvas.java

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,9 @@ public PdfCanvas(PdfStream contentStream, PdfResources resources, PdfDocument do
218218
* @param page page to create canvas from.
219219
*/
220220
public PdfCanvas(PdfPage page) {
221-
this(page, page.getDocument().getReader() != null && page.getDocument().getWriter() != null &&
222-
page.getContentStreamCount() > 0 && page.getLastContentStream().getLength() > 0);
221+
this(page, (page.getDocument().getReader() != null && page.getDocument().getWriter() != null
222+
&& page.getContentStreamCount() > 0 && page.getLastContentStream().getLength() > 0)
223+
|| (page.getRotation() != 0 && page.isIgnorePageRotationForContent()));
223224
}
224225

225226
/**
@@ -235,27 +236,11 @@ public PdfCanvas(PdfPage page, boolean wrapOldContent) {
235236
// Wrap old content in q/Q in order not to get unexpected results because of the CTM
236237
page.newContentStreamBefore().getOutputStream().writeBytes(ByteUtils.getIsoBytes("q\n"));
237238
contentStream.getOutputStream().writeBytes(ByteUtils.getIsoBytes("Q\n"));
238-
if (page.getRotation() != 0 && !page.isIgnoreContentRotation()) {
239-
applyRotation(page);
240-
}
241239
}
242-
243-
244-
}
245-
246-
private void applyRotation(PdfPage page) {
247-
Rectangle rectagle = page.getPageSizeWithRotation();
248-
int rotation = page.getRotation();
249-
switch (rotation) {
250-
case 90:
251-
concatMatrix(0, 1, -1, 0, rectagle.getTop(), 0);
252-
break;
253-
case 180:
254-
concatMatrix(-1, 0, 0, -1, rectagle.getRight(), rectagle.getTop());
255-
break;
256-
case 270:
257-
concatMatrix(0, -1, 1, 0, 0, rectagle.getRight());
258-
break;
240+
if (page.getRotation() != 0 && page.isIgnorePageRotationForContent()
241+
&& (wrapOldContent || !page.isPageRotationInverseMatrixWritten())) {
242+
applyRotation(page);
243+
page.setPageRotationInverseMatrixWritten();
259244
}
260245
}
261246

@@ -2383,4 +2368,20 @@ private PdfArray getDashPatternArray(float[] dashArray, float phase) {
23832368
dashPatternArray.add(new PdfNumber(phase));
23842369
return dashPatternArray;
23852370
}
2371+
2372+
private void applyRotation(PdfPage page) {
2373+
Rectangle rectagle = page.getPageSizeWithRotation();
2374+
int rotation = page.getRotation();
2375+
switch (rotation) {
2376+
case 90:
2377+
concatMatrix(0, 1, -1, 0, rectagle.getTop(), 0);
2378+
break;
2379+
case 180:
2380+
concatMatrix(-1, 0, 0, -1, rectagle.getRight(), rectagle.getTop());
2381+
break;
2382+
case 270:
2383+
concatMatrix(0, -1, 1, 0, 0, rectagle.getRight());
2384+
break;
2385+
}
2386+
}
23862387
}

0 commit comments

Comments
 (0)