diff --git a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/BlockBox.java b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/BlockBox.java index 3a03568fa..65c89b379 100755 --- a/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/BlockBox.java +++ b/openhtmltopdf-core/src/main/java/com/openhtmltopdf/render/BlockBox.java @@ -737,16 +737,25 @@ private void sizeReplacedElement(LayoutContext c, ReplacedElement re) { int intrinsicWidth = re.getIntrinsicWidth(); int intrinsicHeight = re.getIntrinsicHeight(); - cssWidth = !getStyle().isMaxWidthNone() && intrinsicWidth > getCSSMaxWidth(c) ? + cssWidth = !getStyle().isMaxWidthNone() && + (intrinsicWidth > getCSSMaxWidth(c) || cssWidth > getCSSMaxWidth(c)) ? getCSSMaxWidth(c) : cssWidth; cssWidth = getCSSMinWidth(c) > 0 && cssWidth < getCSSMinWidth(c) ? getCSSMinWidth(c) : cssWidth; - cssHeight = !getStyle().isMaxHeightNone() && intrinsicHeight > getCSSMaxHeight(c) ? + cssHeight = !getStyle().isMaxHeightNone() && + (intrinsicHeight > getCSSMaxHeight(c) || cssHeight > getCSSMaxHeight(c)) ? getCSSMaxHeight(c) : cssHeight; cssHeight = getCSSMinHeight(c) > 0 && cssHeight < getCSSMinHeight(c) ? getCSSMinHeight(c) : cssHeight; + if (getStyle().isBorderBox()) { + BorderPropertySet border = getBorder(c); + RectPropertySet padding = getPadding(c); + cssWidth = (int) Math.max(0, cssWidth - border.width() - padding.width()); + cssHeight = (int) Math.max(0, cssHeight - border.height() - padding.height()); + } + int nw; int nh; @@ -798,13 +807,8 @@ private void sizeReplacedElement(LayoutContext c, ReplacedElement re) { nh = intrinsicHeight; } - if (getStyle().isBorderBox()) { - setBorderBoxWidth(c, nw); - setBorderBoxHeight(c, nh); - } else { - setContentWidth(nw); - setHeight(nh); - } + setContentWidth(nw); + setHeight(nh); } public void calcDimensions(LayoutContext c) { diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/expected/replaced-sizing-img.pdf b/openhtmltopdf-examples/src/main/resources/visualtest/expected/replaced-sizing-img.pdf index 739574249..bee419386 100644 Binary files a/openhtmltopdf-examples/src/main/resources/visualtest/expected/replaced-sizing-img.pdf and b/openhtmltopdf-examples/src/main/resources/visualtest/expected/replaced-sizing-img.pdf differ diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/expected/replaced-sizing-svg.pdf b/openhtmltopdf-examples/src/main/resources/visualtest/expected/replaced-sizing-svg.pdf new file mode 100644 index 000000000..a0403a71f Binary files /dev/null and b/openhtmltopdf-examples/src/main/resources/visualtest/expected/replaced-sizing-svg.pdf differ diff --git a/openhtmltopdf-examples/src/main/resources/visualtest/html/replaced-sizing-svg.html b/openhtmltopdf-examples/src/main/resources/visualtest/html/replaced-sizing-svg.html new file mode 100644 index 000000000..1bf5f4ddf --- /dev/null +++ b/openhtmltopdf-examples/src/main/resources/visualtest/html/replaced-sizing-svg.html @@ -0,0 +1,69 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 6fe7c3d35..5c95b5d89 100644 --- a/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java +++ b/openhtmltopdf-examples/src/test/java/com/openhtmltopdf/visualregressiontests/VisualRegressionTest.java @@ -744,6 +744,15 @@ public void testReplacedSizingImg() throws IOException { assertTrue(vt.runTest("replaced-sizing-img")); } + /** + * Tests various sizing properties for replaced SVG images including box-sizing, + * min/max, etc. + */ + @Test + public void testReplacedSizingSvg() throws IOException { + assertTrue(vt.runTest("replaced-sizing-svg", WITH_SVG)); + } + // TODO: // + Elements that appear just on generated overflow pages. // + content property (page counters, etc) diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java index 5d0798430..41eeb0772 100644 --- a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java +++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGDrawer.java @@ -30,7 +30,7 @@ public SVGImage buildSVGImage(Element svgElement, Box box, CssContext c, double cssMaxWidth = CalculatedStyle.getCSSMaxWidth(c, box); double cssMaxHeight = CalculatedStyle.getCSSMaxHeight(c, box); - BatikSVGImage img = new BatikSVGImage(svgElement, cssWidth, cssHeight, + BatikSVGImage img = new BatikSVGImage(svgElement, box, cssWidth, cssHeight, cssMaxWidth, cssMaxHeight, dotsPerPixel); img.setFontResolver(fontResolver); return img; diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGImage.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGImage.java index bea5134d7..10a84cd1a 100644 --- a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGImage.java +++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/BatikSVGImage.java @@ -14,6 +14,7 @@ import com.openhtmltopdf.extend.OutputDevice; import com.openhtmltopdf.extend.SVGDrawer.SVGImage; +import com.openhtmltopdf.render.Box; import com.openhtmltopdf.render.RenderingContext; import com.openhtmltopdf.svgsupport.PDFTranscoder.OpenHtmlFontResolver; import com.openhtmltopdf.util.XRLog; @@ -27,12 +28,12 @@ public class BatikSVGImage implements SVGImage { private PDFTranscoder pdfTranscoder; - public BatikSVGImage(Element svgElement, double cssWidth, double cssHeight, + public BatikSVGImage(Element svgElement, Box box, double cssWidth, double cssHeight, double cssMaxWidth, double cssMaxHeight, double dotsPerPixel) { this.svgElement = svgElement; this.dotsPerPixel = dotsPerPixel; - this.pdfTranscoder = new PDFTranscoder(cssWidth, cssHeight); + this.pdfTranscoder = new PDFTranscoder(box, dotsPerPixel, cssWidth, cssHeight); if (cssWidth >= 0) { this.pdfTranscoder.addTranscodingHint( SVGAbstractTranscoder.KEY_WIDTH, diff --git a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java index 53d8640be..c638e8dd3 100644 --- a/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java +++ b/openhtmltopdf-svg-support/src/main/java/com/openhtmltopdf/svgsupport/PDFTranscoder.java @@ -8,6 +8,7 @@ import com.openhtmltopdf.extend.OutputDevice; import com.openhtmltopdf.extend.OutputDeviceGraphicsDrawer; import com.openhtmltopdf.layout.SharedContext; +import com.openhtmltopdf.render.Box; import com.openhtmltopdf.render.RenderingContext; import com.openhtmltopdf.util.XRLog; import org.apache.batik.bridge.FontFace; @@ -21,6 +22,8 @@ import java.awt.*; import java.awt.font.TextAttribute; +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; import java.io.InputStream; import java.util.HashMap; import java.util.List; @@ -31,17 +34,22 @@ public class PDFTranscoder extends SVGAbstractTranscoder { private OutputDevice outputDevice; private double x; private double y; + private final Box box; + private RenderingContext ctx; + private final double dotsPerPixel; - public PDFTranscoder(double width, double height ) { + public PDFTranscoder(Box box, double dotsPerPixel, double width, double height) { + this.box = box; this.width = (float)width; this.height = (float)height; + this.dotsPerPixel = dotsPerPixel; } public void setRenderingParameters(OutputDevice od, RenderingContext ctx, double x, double y, OpenHtmlFontResolver fontResolver) { this.x = x; this.y = y; this.outputDevice = od; - + this.ctx = ctx; this.fontResolver = fontResolver; } @@ -199,14 +207,71 @@ protected void transcode(Document svg, String uri, TranscoderOutput out) throws // is called before our constructor is called in the super constructor. this.userAgent = new OpenHtmlUserAgent(this.fontResolver); super.transcode(svg, uri, out); - - outputDevice.drawWithGraphics((float)x, (float)y, width, height, new OutputDeviceGraphicsDrawer() { + + int intrinsicWidth = (int) width; + int intrinsicHeight = (int) height; + + Rectangle contentBounds = box.getContentAreaEdge(box.getAbsX(), box.getAbsY(), ctx); + + int desiredWidth = (int) (contentBounds.width / this.dotsPerPixel); + int desiredHeight = (int) (contentBounds.height / this.dotsPerPixel); + + boolean transformed = false; + AffineTransform scale = null; + + if (width == 0 || height == 0) { + // Do nothing... + } + else if (desiredWidth > intrinsicWidth && + desiredHeight > intrinsicHeight) { + + double rw = (double) desiredWidth / width; + double rh = (double) desiredHeight / height; + + double factor = Math.min(rw, rh); + scale = AffineTransform.getScaleInstance(factor, factor); + transformed = true; + } else if (desiredWidth < intrinsicWidth && + desiredHeight < intrinsicHeight) { + double rw = (double) desiredWidth / width; + double rh = (double) desiredHeight / height; + + double factor = Math.max(rw, rh); + scale = AffineTransform.getScaleInstance(factor, factor); + transformed = true; + } + + AffineTransform inverseScale = null; + try { + if (transformed) { + inverseScale = scale.createInverse(); + } + } catch (NoninvertibleTransformException e) { + transformed = false; + } + final AffineTransform scale2 = scale; + final AffineTransform inverse2 = inverseScale; + final boolean transformed2 = transformed; + + outputDevice.drawWithGraphics( + (float) x, + (float) y, + (float) (contentBounds.width / this.dotsPerPixel), + (float) (contentBounds.height / this.dotsPerPixel), + new OutputDeviceGraphicsDrawer() { @Override public void render(Graphics2D graphics2D) { + if (transformed2) { + graphics2D.transform(scale2); + } /* * Do the real paint */ PDFTranscoder.this.root.paint(graphics2D); + + if (transformed2) { + graphics2D.transform(inverse2); + } } }); }