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.