diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/ContentPropertyBuilder.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/ContentPropertyBuilder.java index 98b652f1d..2628490be 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/ContentPropertyBuilder.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/css/parser/property/ContentPropertyBuilder.java @@ -62,7 +62,8 @@ public List buildDeclarations( short type = value.getPrimitiveType(); if (type == CSSPrimitiveValue.CSS_URI) { - continue; + // We have an image. + resultValues.add(value); } else if (type == CSSPrimitiveValue.CSS_STRING) { resultValues.add(value); } else if (value.getPropertyValueType() == PropertyValue.VALUE_TYPE_FUNCTION) { diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/BoxBuilder.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/BoxBuilder.java index f76778f93..f774afee3 100644 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/BoxBuilder.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/layout/BoxBuilder.java @@ -804,6 +804,21 @@ private static List createGeneratedContentList( short type = value.getPrimitiveType(); if (type == CSSPrimitiveValue.CSS_STRING) { content = value.getStringValue(); + } else if (type == CSSPrimitiveValue.CSS_URI) { + Element creator = element != null ? element : c.getRootLayer().getMaster().getElement(); + Document doc = creator.getOwnerDocument(); + Element img = doc.createElement("img"); + img.setAttribute("src", value.getStringValue()); + creator.appendChild(img); + + BlockBox iB = new BlockBox(); + iB.setElement(img); + iB.setPseudoElementOrClass(peName); + iB.setStyle(style.createAnonymousStyle(IdentValue.INLINE_BLOCK)); + + info.setContainsBlockLevelContent(true); + + result.add(iB); } else if (value.getPropertyValueType() == PropertyValue.VALUE_TYPE_FUNCTION) { if (mode == CONTENT_LIST_DOCUMENT && isAttrFunction(value.getFunction())) { content = getAttributeValue(value.getFunction(), element); @@ -933,10 +948,46 @@ private static List createGeneratedContent( return Collections.emptyList(); } + ChildBoxInfo childInfo = new ChildBoxInfo(); List inlineBoxes = createGeneratedContentList( - c, element, property, peName, style, CONTENT_LIST_DOCUMENT, null); + c, element, property, peName, style, CONTENT_LIST_DOCUMENT, childInfo); + + if (childInfo.isContainsBlockLevelContent()) { + List inlines = new ArrayList<>(); + + BlockBox result = createBlockBox(style.createAnonymousStyle(IdentValue.INLINE_BLOCK), info, true); + + result.setStyle(style.createAnonymousStyle(IdentValue.INLINE_BLOCK)); + result.setElement(element); + result.setChildrenContentType(BlockBox.CONTENT_BLOCK); + result.setPseudoElementOrClass(peName); - if (style.isInline()) { + CalculatedStyle anon = style.createAnonymousStyle(IdentValue.INLINE); + + for (Iterator i = inlineBoxes.iterator(); i.hasNext();) { + Styleable b = (Styleable) i.next(); + + if (b instanceof BlockBox) { + if (!inlines.isEmpty()) { + createAnonymousInlineBlock(c.getSharedContext(), result, inlines, null); + inlines.clear(); + } + result.addChild((BlockBox) b); + } else { + InlineBox iB = (InlineBox) b; + + iB.setStyle(anon); + iB.applyTextTransform(); + + inlines.add(iB); + } + } + + if (!inlines.isEmpty()) { + createAnonymousInlineBlock(c.getSharedContext(), result, inlines, null); + } + return Collections.singletonList(result); + } else if (style.isInline()) { for (Iterator i = inlineBoxes.iterator(); i.hasNext();) { InlineBox iB = (InlineBox) i.next(); iB.setStyle(style); @@ -1387,11 +1438,19 @@ private static void insertAnonymousBlocks( createAnonymousBlock(c, parent, inline, savedParents); } + private static void createAnonymousInlineBlock(SharedContext c, Box parent, List inline, List savedParents) { + createAnonymousBlock(c, parent, inline, savedParents, IdentValue.INLINE_BLOCK); + } + private static void createAnonymousBlock(SharedContext c, Box parent, List inline, List savedParents) { + createAnonymousBlock(c, parent, inline, savedParents, IdentValue.BLOCK); + } + + private static void createAnonymousBlock(SharedContext c, Box parent, List inline, List savedParents, IdentValue display) { WhitespaceStripper.stripInlineContent(inline); if (inline.size() > 0) { AnonymousBlockBox anon = new AnonymousBlockBox(parent.getElement()); - anon.setStyle(parent.getStyle().createAnonymousStyle(IdentValue.BLOCK)); + anon.setStyle(parent.getStyle().createAnonymousStyle(display)); anon.setAnonymous(true); if (savedParents != null && savedParents.size() > 0) { anon.setOpenInlineBoxes(savedParents); diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/html/content-property-capabilities.html b/openhtmltopdf-examples/src/main/resources/visualtest/html/content-property-capabilities.html new file mode 100644 index 000000000..3f05b0b3f --- /dev/null +++ b/openhtmltopdf-examples/src/main/resources/visualtest/html/content-property-capabilities.html @@ -0,0 +1,44 @@ + + + + + + +
ONE
+
WORLD
+
With images:
+ + diff --git a/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java b/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java index e3b4b1ecb..e648cbec1 100644 --- a/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java +++ b/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java @@ -1007,6 +1007,15 @@ public void testIssue446LangSelector() throws IOException { assertTrue(vt.runTest("issue-446-lang-selector")); } + /** + * Tests what the CSS content property is capable of. + */ + @Test + @Ignore // Working but with content images behaving as blocks rather than inline-blocks. + public void testContentPropertyCapabilities() throws IOException { + assertTrue(vt.runTest("content-property-capabilities")); + } + /** * Tests that aligned right text doesn't have trailing spaces * that cause ragged text on the right.