diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java index 9d54b1b86..b9ae52b87 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/context/StyleReference.java @@ -36,6 +36,7 @@ import com.openhtmltopdf.css.extend.lib.DOMTreeResolver; import com.openhtmltopdf.css.newmatch.CascadedStyle; import com.openhtmltopdf.css.newmatch.PageInfo; +import com.openhtmltopdf.css.newmatch.Selector; import com.openhtmltopdf.css.parser.CSSPrimitiveValue; import com.openhtmltopdf.css.sheet.PropertyDeclaration; import com.openhtmltopdf.css.sheet.Stylesheet; @@ -85,6 +86,10 @@ public CalculatedStyle getRootElementStyle() { } } + public List getSelectors() { + return _matcher.getSelectors(); + } + /** * Sets the documentContext attribute of the StyleReference object * 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 2a5336944..b62c15089 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 @@ -302,6 +302,87 @@ public final class CSSName implements Comparable { new PrimitivePropertyBuilders.FSKeepWithInline() ); + /** + * Layer identifier (document-scoped). + */ + public final static CSSName FS_OCG_ID = + addProperty( + "-fs-ocg-id", + PRIMITIVE, + IdentValue.NONE.asString(), + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOcId() + ); + /** + * Layer name, suitable for UI presentation (see {@code Name} entry in optional content group + * dictionary [ISO:32000-1:8.11.2.1]). + */ + public final static CSSName FS_OCG_LABEL = + addProperty( + "-fs-ocg-label", + PRIMITIVE, + IdentValue.NONE.asString(), + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOcgLabel() + ); + /** + * Layer parent {@link #FS_OCG_ID reference}. + */ + public final static CSSName FS_OCG_PARENT = + addProperty( + "-fs-ocg-parent", + PRIMITIVE, + IdentValue.NONE.asString(), + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOcId() + ); + /** + * Layer visibility. + */ + public final static CSSName FS_OCG_VISIBILITY = + addProperty( + "-fs-ocg-visibility", + PRIMITIVE, + IdentValue.VISIBLE.asString(), + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOcgVisibility() + ); + /** + * Layer membership identifier (document-scoped). + */ + public final static CSSName FS_OCM_ID = + addProperty( + "-fs-ocm-id", + PRIMITIVE, + IdentValue.NONE.asString(), + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOcId() + ); + /** + * Layer visibility policy (see {@code BaseState}, {@code ON}, {@code OFF} entries in {@code D} + * entry in optional content configuration dictionary [ISO:32000-1:8.11.4.3]). + */ + public final static CSSName FS_OCM_VISIBLE = + addProperty( + "-fs-ocm-visible", + PRIMITIVE, + IdentValue.ANY_VISIBLE.asString(), + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOcmVisible() + ); + /** + * Layers belonging to the membership. + * + *

Value: list of {@link #FS_OCG_ID layer references}.

+ */ + public final static CSSName FS_OCM_OCGS = + addProperty( + "-fs-ocm-ocgs", + PRIMITIVE, + IdentValue.NONE.asString(), + NOT_INHERITED, + new PrimitivePropertyBuilders.FSOcIds()); + /** * Unique CSSName instance for CSS2 property. */ diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/IdentValue.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/IdentValue.java index ca62c822a..48dbfeec4 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/IdentValue.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/constants/IdentValue.java @@ -60,7 +60,11 @@ public class IdentValue implements FSDerivedValue { public final int FS_ID; public final static IdentValue ABSOLUTE = addValue("absolute"); + public final static IdentValue ALL_HIDDEN = addValue("all-hidden"); + public final static IdentValue ALL_VISIBLE = addValue("all-visible"); public final static IdentValue ALWAYS = addValue("always"); + public final static IdentValue ANY_HIDDEN = addValue("any-hidden"); + public final static IdentValue ANY_VISIBLE = addValue("any-visible"); public final static IdentValue ARMENIAN = addValue("armenian"); public final static IdentValue AUTO = addValue("auto"); public final static IdentValue AVOID = addValue("avoid"); diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/newmatch/Matcher.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/newmatch/Matcher.java index c7343e953..e9e2a9bf1 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/newmatch/Matcher.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/newmatch/Matcher.java @@ -139,6 +139,10 @@ public PageInfo getPageCascadedStyle(String pageName, String pseudoPage) { public List getFontFaceRules() { return _fontFaceRules; } + + public List getSelectors() { + return docMapper.axes; + } public boolean isVisitedStyled(Object e) { return _visitElements.contains(e); 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 46717cc58..167c817bb 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 @@ -184,7 +184,51 @@ protected BitSet getAllowed() { return BORDER_STYLES; } } - + + private static class GenericString extends AbstractPropertyBuilder { + private static final BitSet ALLOWED = setFor( + new IdentValue[] { IdentValue.NONE }); + + @Override + public List buildDeclarations( + CSSName cssName, List values, int origin, boolean important, boolean inheritAllowed) { + checkValueCount(cssName, 1, values.size()); + return Collections.singletonList( + checkDeclaration(cssName, values.get(0), origin, important, inheritAllowed)); + } + + protected PropertyDeclaration checkDeclaration( + CSSName cssName, CSSPrimitiveValue value, int origin, boolean important, boolean inheritAllowed) { + checkInheritAllowed(value, inheritAllowed); + if (value.getCssValueType() != CSSValue.CSS_INHERIT) { + switch (value.getPrimitiveType()) { + case CSSPrimitiveValue.CSS_STRING: + /* NOOP: Any custom string value accepted. */ + break; + case CSSPrimitiveValue.CSS_IDENT: + IdentValue ident = checkIdent(cssName, value); + checkValidity(cssName, ALLOWED, ident); + break; + default: + throw new CSSParseException("Value '" + value + "' is invalid for " + cssName, -1); + } + } + return new PropertyDeclaration(cssName, value, important, origin); + } + } + + private static class GenericStrings extends GenericString { + @Override + public List buildDeclarations( + CSSName cssName, List values, int origin, boolean important, boolean inheritAllowed) { + List declarations = new ArrayList<>(); + for (PropertyValue value : values) { + declarations.add(checkDeclaration(cssName, value, origin, important, inheritAllowed)); + } + return Collections.unmodifiableList(declarations); + } + } + public static class Direction extends SingleIdent { @Override protected BitSet getAllowed() { @@ -1014,6 +1058,38 @@ protected BitSet getAllowed() { } } + public static class FSOcgLabel extends GenericString { + } + + public static class FSOcgVisibility extends SingleIdent { + private static final BitSet ALLOWED = setFor( + new IdentValue[] { + IdentValue.VISIBLE, IdentValue.HIDDEN }); + + @Override + protected BitSet getAllowed() { + return ALLOWED; + } + } + + public static class FSOcId extends GenericString { + } + + public static class FSOcIds extends GenericStrings { + }; + + public static class FSOcmVisible extends SingleIdent { + private static final BitSet ALLOWED = setFor( + new IdentValue[] { + IdentValue.ALL_HIDDEN, IdentValue.ALL_VISIBLE, IdentValue.ANY_HIDDEN, + IdentValue.ANY_VISIBLE }); + + @Override + protected BitSet getAllowed() { + return ALLOWED; + } + } + public static class Left extends LengthLikeWithAuto { } diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/sheet/Ruleset.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/sheet/Ruleset.java index 32c56bd4a..dbec8b512 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/sheet/Ruleset.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/sheet/Ruleset.java @@ -105,4 +105,11 @@ public void addInvalidProperty(InvalidPropertyDeclaration invalidPropertyDeclara public List getInvalidPropertyDeclarations() { return _invalidProperties == null ? Collections.emptyList() : _invalidProperties; } + + @Override + public String toString() { + StringBuilder b=new StringBuilder(); + toCSS(b); + return b.toString(); + } } diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/AbstractOutputDevice.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/AbstractOutputDevice.java index 43c1439cd..edd66e865 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/AbstractOutputDevice.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/AbstractOutputDevice.java @@ -231,6 +231,11 @@ public void paintBackground(RenderingContext c, Box box) { paintBackground0(c, box.getStyle(), backgroundBounds, backgroundBounds, border); } + protected void onBackgroundPaint(RenderingContext c, CalculatedStyle style, + Rectangle backgroundBounds, Rectangle bgImageContainer, + BorderPropertySet border) { + } + private void paintBackground0( RenderingContext c, CalculatedStyle style, Rectangle backgroundBounds, Rectangle bgImageContainer, @@ -240,6 +245,8 @@ private void paintBackground0( return; } + onBackgroundPaint(c, style, backgroundBounds, bgImageContainer, border); + FSColor backgroundColor = style.getBackgroundColor(); List bgImages = style.getBackgroundImages(); diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/displaylist/DisplayListPainter.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/displaylist/DisplayListPainter.java index 1176e3a44..cf42deb53 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/displaylist/DisplayListPainter.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/displaylist/DisplayListPainter.java @@ -75,6 +75,9 @@ private void paintBackgroundAndBorders(RenderingContext c, List box.paintBackground(c); box.paintBorder(c); + c.getOutputDevice().endStructure(innerToken); + c.getOutputDevice().endStructure(outerToken); + if (collapsedTableBorders != null && box instanceof TableCellBox) { TableCellBox cell = (TableCellBox) box; @@ -88,9 +91,6 @@ private void paintBackgroundAndBorders(RenderingContext c, List } } } - - c.getOutputDevice().endStructure(innerToken); - c.getOutputDevice().endStructure(outerToken); } } } diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/util/LogMessageId.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/util/LogMessageId.java index c4eab9b6d..792af132d 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/util/LogMessageId.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/util/LogMessageId.java @@ -144,6 +144,7 @@ enum LogMessageId1Param implements LogMessageId { GENERAL_PDF_ACCESSIBILITY_NO_TITLE_TEXT_PROVIDED_FOR(XRLog.GENERAL, "PDF/UA - No title text provided for {}."), GENERAL_PDF_COULD_NOT_FIND_VALID_TARGET_FOR_BOOKMARK(XRLog.GENERAL, "Could not find valid target for bookmark. Bookmark href = {}"), GENERAL_PDF_COULD_NOT_FIND_VALID_TARGET_FOR_LINK(XRLog.GENERAL, "Could not find valid target for link. Link href = {}"), + GENERAL_PDF_LAYER_END(XRLog.GENERAL, "OC: {} END"), GENERAL_PDF_URI_IN_HREF_IS_NOT_A_VALID_URI(XRLog.GENERAL, "'{}' in href is not a valid URI, will be skipped"), GENERAL_PDF_FOUND_FORM_CONTROL_WITH_NO_ENCLOSING_FORM(XRLog.GENERAL, "Found form control ({}) with no enclosing form. Ignoring."), GENERAL_PDF_A_ELEMENT_DOES_NOT_HAVE_OPTION_CHILDREN(XRLog.GENERAL, "A <{}> element does not have