From 5cadc6dcdf530b47687baf147dc1e42987b0abce Mon Sep 17 00:00:00 2001 From: danfickle Date: Sun, 12 Aug 2018 16:45:48 +1000 Subject: [PATCH] #180 #126 Implement CSS page property -fs-overflow-pages-direction. Controls whether cut-off content to the right (ltr) of the page is inserted or to the left (rtl). --- .../openhtmltopdf/css/constants/CSSName.java | 16 ++++++++++++++++ .../property/PrimitivePropertyBuilders.java | 10 ++++++++++ .../java/com/openhtmltopdf/render/PageBox.java | 17 +++++++++++++---- .../openhtmltopdf/pdfboxout/PdfBoxRenderer.java | 3 ++- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/CSSName.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/CSSName.java index 365065171..732e266bf 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/CSSName.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/CSSName.java @@ -1491,6 +1491,9 @@ public final class CSSName implements Comparable { new PrimitivePropertyBuilders.BoxSizing() ); + /** + * The maximum number of inserted shadow pages to insert for cut-off content. + */ public final static CSSName FS_MAX_OVERFLOW_PAGES = addProperty( "-fs-max-overflow-pages", @@ -1499,6 +1502,19 @@ public final class CSSName implements Comparable { NOT_INHERITED, new PrimitivePropertyBuilders.FSMaxOverflowPages() ); + + /** + * Whether cut-off content to the right (default) of the page or left + * of the page should be inserted as shadow pages. + */ + public final static CSSName FS_OVERFLOW_PAGES_DIRECTION = + addProperty( + "-fs-overflow-pages-direction", + PRIMITIVE, + "ltr", + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOverflowPagesDirection() + ); /** diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/PrimitivePropertyBuilders.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/PrimitivePropertyBuilders.java index 2cf48613a..ba978927e 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/PrimitivePropertyBuilders.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/PrimitivePropertyBuilders.java @@ -1855,4 +1855,14 @@ protected boolean isNegativeValuesAllowed() { return false; } } + + public static class FSOverflowPagesDirection extends SingleIdent { + private static final BitSet ALLOWED = setFor(new IdentValue[] { IdentValue.LTR, IdentValue.RTL }); + + @Override + protected BitSet getAllowed() { + return ALLOWED; + } + } + } diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/PageBox.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/PageBox.java index 6b1f6ebac..a2b208062 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/PageBox.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/PageBox.java @@ -26,8 +26,6 @@ import java.io.Writer; import java.util.Iterator; import java.util.List; -import java.util.Locale; - import org.w3c.dom.Element; import org.w3c.dom.css.CSSPrimitiveValue; @@ -276,11 +274,14 @@ public Rectangle getDocumentCoordinatesContentBounds(CssContext c) { /** * Get the shadow page (a page inserted to carry cut off content) content area of the layed out document. * For example: If a page one is 100 units high and 150 wide and has a margin of 10 then this will return a - * rect(130, 0, 130, 80) for the first shadow page and a rect(260, 0, 130, 80) for the second shadow page. + * rect(130, 0, 130, 80) for the first shadow page and a rect(260, 0, 130, 80) for the second shadow page + * assuming cut-off direction is LTR. + * + * For RTL the rects would be rect(-130, 0, 130, 80) and rect(-260, 0, 130, 80). */ public Rectangle getDocumentCoordinatesContentBoundsForInsertedPage(CssContext c, int shadowPageNumber) { return new Rectangle( - getContentWidth(c) * (shadowPageNumber + 1), + getContentWidth(c) * (shadowPageNumber + 1) * (getCutOffPageDirection() == IdentValue.LTR ? 1 : -1), getPaintingTop(), getContentWidth(c), getContentHeight(c)); @@ -300,6 +301,14 @@ public int getMaxInsertedPages() { return getStyle().fsMaxOverflowPages(); } + /** + * @return Either ltr (should insert cut-off content to the right of the page) or + * rtl (should insert cut-off content to the left of the page). + */ + public IdentValue getCutOffPageDirection() { + return getStyle().getIdent(CSSName.FS_OVERFLOW_PAGES_DIRECTION); + } + public Rectangle getPagedViewClippingBounds(CssContext cssCtx, int additionalClearance) { Rectangle result = new Rectangle( additionalClearance + diff --git a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java index adbbd568b..7b9a908e9 100644 --- a/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java +++ b/openhtmltopdf-pdfbox/src/main/java/com/openhtmltopdf/pdfboxout/PdfBoxRenderer.java @@ -24,6 +24,7 @@ import com.openhtmltopdf.bidi.BidiSplitterFactory; import com.openhtmltopdf.bidi.SimpleBidiReorderer; import com.openhtmltopdf.context.StyleReference; +import com.openhtmltopdf.css.constants.IdentValue; import com.openhtmltopdf.css.style.CalculatedStyle; import com.openhtmltopdf.extend.*; import com.openhtmltopdf.layout.BoxBuilder; @@ -610,7 +611,7 @@ private void writePDFFast(List pages, RenderingContext c, Rectangle2D f if (!pageOperations.shadowPages().isEmpty()) { // TODO. - int translateX = (int) (firstPageSize.getWidth() * _outputDevice.getDotsPerPoint()); + int translateX = (int) (firstPageSize.getWidth() * _outputDevice.getDotsPerPoint()) * (currentPage.getCutOffPageDirection() == IdentValue.LTR ? 1 : -1); for (DisplayListPageContainer shadowPage : pageOperations.shadowPages()) { PDPage shadowPdPage = new PDPage(new PDRectangle((float) firstPageSize.getWidth(), (float) firstPageSize.getHeight())); PDPageContentStream shadowCs = new PDPageContentStream(doc, shadowPdPage, AppendMode.APPEND, !_testMode);