From: Simon Steiner Date: Mon, 15 Jul 2024 12:10:58 +0000 (+0100) Subject: FOP-3135: SVG tspan content is displayed out of place by João André Gonçalves X-Git-Tag: 2_10~16 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ef173cf4b2da33f2b84df3d17ecb71c1273c6e20;p=xmlgraphics-fop.git FOP-3135: SVG tspan content is displayed out of place by João André Gonçalves --- diff --git a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java index 9fec79bf4..443b02028 100644 --- a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java +++ b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java @@ -160,6 +160,10 @@ public class FOUserAgent { return FOUserAgent.this.getTargetResolution(); } + public float getSourceResolution() { + return FOUserAgent.this.getSourceResolution(); + } + public Source resolveURI(String uri) { return FOUserAgent.this.resolveURI(uri); } diff --git a/fop-core/src/main/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/fop-core/src/main/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index b5d8626f9..02f1d6871 100644 --- a/fop-core/src/main/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/fop-core/src/main/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -35,7 +35,6 @@ import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.UserAgent; import org.apache.batik.gvt.GraphicsNode; -import org.apache.xmlgraphics.image.GraphicsConstants; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageFlavor; @@ -74,13 +73,7 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { + svg.getRootNamespace()); } - //Prepare - float pxToMillimeter = UnitConv.IN2MM / GraphicsConstants.DEFAULT_DPI; - Number ptm = (Number)hints.get(ImageProcessingHints.SOURCE_RESOLUTION); - if (ptm != null) { - pxToMillimeter = (float)(UnitConv.IN2MM / ptm.doubleValue()); - } - UserAgent ua = createBatikUserAgent(pxToMillimeter); + UserAgent ua = createBatikUserAgent(hints); GVTBuilder builder = new GVTBuilder(); final ImageManager imageManager = (ImageManager)hints.get( @@ -118,14 +111,23 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { return g2dImage; } + private float getResolution(Map hints, Object key) { + Number res = (Number) hints.get(key); + + if (res != null) { + return res.floatValue(); + } + return UnitConv.IN2PT; + } + /** * Creates a user agent for Batik. Override to provide your own user agent. - * @param pxToMillimeter the source resolution (in px per millimeter) * @return the newly created user agent */ - protected SimpleSVGUserAgent createBatikUserAgent(float pxToMillimeter) { - return new SimpleSVGUserAgent(pxToMillimeter, new AffineTransform(), - DefaultFontFamilyResolver.SINGLETON) { + protected SimpleSVGUserAgent createBatikUserAgent(Map hints) { + return new SimpleSVGUserAgent(new AffineTransform(), + DefaultFontFamilyResolver.SINGLETON, + getResolution(hints, ImageProcessingHints.SOURCE_RESOLUTION)) { /** {@inheritDoc} */ public void displayMessage(String message) { //TODO Refine and pipe through to caller diff --git a/fop-core/src/main/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/fop-core/src/main/java/org/apache/fop/image/loader/batik/PreloaderSVG.java index 7df9a6cb6..4d8f6d123 100644 --- a/fop-core/src/main/java/org/apache/fop/image/loader/batik/PreloaderSVG.java +++ b/fop-core/src/main/java/org/apache/fop/image/loader/batik/PreloaderSVG.java @@ -161,9 +161,9 @@ public class PreloaderSVG extends AbstractImagePreloader { private ImageInfo createImageInfo(String uri, ImageContext context, SVGDocument doc) { Element e = doc.getRootElement(); - float pxUnitToMillimeter = UnitConv.IN2MM / context.getSourceResolution(); - UserAgent userAg = new SimpleSVGUserAgent(pxUnitToMillimeter, - new AffineTransform(), DefaultFontFamilyResolver.SINGLETON) { + UserAgent userAg = new SimpleSVGUserAgent( + new AffineTransform(), DefaultFontFamilyResolver.SINGLETON, + context.getSourceResolution()) { /** {@inheritDoc} */ public void displayMessage(String message) { diff --git a/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTranscoder.java b/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTranscoder.java index 0b3e6985f..2aca0cd96 100644 --- a/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTranscoder.java +++ b/fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTranscoder.java @@ -251,7 +251,7 @@ public abstract class AbstractFOPTranscoder extends SVGAbstractTranscoder implem protected void setupImageInfrastructure(final String baseURI) { final ImageContext imageContext = new ImageContext() { public float getSourceResolution() { - return UnitConv.IN2MM / userAgent.getPixelUnitToMillimeter(); + return userAgent.getSourceResolution(); } }; this.imageManager = new ImageManager(imageContext); @@ -265,6 +265,10 @@ public abstract class AbstractFOPTranscoder extends SVGAbstractTranscoder implem return getDeviceResolution(); } + public float getSourceResolution() { + return getDeviceResolution(); + } + public Source resolveURI(String uri) { try { ParsedURL url = new ParsedURL(baseURI, uri); @@ -371,7 +375,7 @@ public abstract class AbstractFOPTranscoder extends SVGAbstractTranscoder implem return (Float) getTranscodingHints().get(key); } else { // return 0.3528f; // 72 dpi - return UnitConv.IN2MM / 96; //96dpi = 0.2645833333333333333f; + return UnitConv.IN2MM / getSourceResolution(); //96dpi = 0.2645833333333333333f; } } diff --git a/fop-core/src/main/java/org/apache/fop/svg/SVGUserAgent.java b/fop-core/src/main/java/org/apache/fop/svg/SVGUserAgent.java index 6a4d9d0de..01d6e487c 100644 --- a/fop-core/src/main/java/org/apache/fop/svg/SVGUserAgent.java +++ b/fop-core/src/main/java/org/apache/fop/svg/SVGUserAgent.java @@ -40,7 +40,7 @@ public class SVGUserAgent extends SimpleSVGUserAgent { * @param at the current transform */ public SVGUserAgent(FOUserAgent foUserAgent, FontFamilyResolver fontFamilyResolver, AffineTransform at) { - super(foUserAgent.getSourcePixelUnitToMillimeter(), at, fontFamilyResolver); + super(at, fontFamilyResolver, foUserAgent.getSourceResolution()); this.eventProducer = SVGEventProducer.Provider.get(foUserAgent.getEventBroadcaster()); } diff --git a/fop-core/src/main/java/org/apache/fop/svg/SimpleSVGUserAgent.java b/fop-core/src/main/java/org/apache/fop/svg/SimpleSVGUserAgent.java index 0267cb683..d4075c73b 100644 --- a/fop-core/src/main/java/org/apache/fop/svg/SimpleSVGUserAgent.java +++ b/fop-core/src/main/java/org/apache/fop/svg/SimpleSVGUserAgent.java @@ -31,6 +31,8 @@ import org.xml.sax.SAXException; import org.apache.batik.bridge.FontFamilyResolver; import org.apache.batik.bridge.UserAgentAdapter; +import org.apache.xmlgraphics.util.UnitConv; + /** * A simple SVG user agent. * This is an implementation of the Batik SVG user agent. It ignores any message output sent @@ -40,19 +42,17 @@ public class SimpleSVGUserAgent extends UserAgentAdapter { private AffineTransform currentTransform; - private float pixelUnitToMillimeter; - private final FontFamilyResolver fontFamilyResolver; /** * Creates a new user agent. - * @param pixelUnitToMM the pixel to millimeter conversion factor currently in effect * @param at the current transform */ - public SimpleSVGUserAgent(float pixelUnitToMM, AffineTransform at, FontFamilyResolver fontFamilyResolver) { + public SimpleSVGUserAgent(AffineTransform at, FontFamilyResolver fontFamilyResolver, + float sourceResolution) { this.fontFamilyResolver = fontFamilyResolver; - pixelUnitToMillimeter = pixelUnitToMM; currentTransform = at; + setSourceResolution(sourceResolution); } /** @@ -60,7 +60,14 @@ public class SimpleSVGUserAgent extends UserAgentAdapter { * @return the pixel unit to millimeter conversion factor */ public float getPixelUnitToMillimeter() { - return pixelUnitToMillimeter; + return UnitConv.IN2MM / getSourceResolution(); + } + + /** + * @return medium font size adapted to the resolution + */ + public float getMediumFontSize() { + return 12f * UnitConv.IN2MM / (UnitConv.IN2PT * getPixelUnitToMillimeter()); } /** diff --git a/fop-core/src/test/java/org/apache/fop/svg/NativeTextPainterTest.java b/fop-core/src/test/java/org/apache/fop/svg/NativeTextPainterTest.java index aa3019c9c..1890e4c67 100644 --- a/fop-core/src/test/java/org/apache/fop/svg/NativeTextPainterTest.java +++ b/fop-core/src/test/java/org/apache/fop/svg/NativeTextPainterTest.java @@ -32,6 +32,8 @@ import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.TextPainter; import org.apache.batik.gvt.GraphicsNode; +import org.apache.xmlgraphics.util.UnitConv; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopFactory; import org.apache.fop.fonts.FontInfo; @@ -41,8 +43,12 @@ import org.apache.fop.svg.font.FOPFontFamilyResolverImpl; abstract class NativeTextPainterTest { protected final Graphics2D runTest(String testcase, OperatorValidator validator) throws Exception { - FontInfo fontInfo = createFontInfo(); - BridgeContext bridgeContext = createBridgeContext(fontInfo); + return runTest(testcase, createFontInfo(), validator, UnitConv.IN2PT); + } + + protected final Graphics2D runTest(String testcase, FontInfo fontInfo, OperatorValidator validator, + int sourceRes) throws Exception { + BridgeContext bridgeContext = createBridgeContext(fontInfo, sourceRes); GraphicsNode svg = loadSVG(bridgeContext, testcase); Graphics2D g2d = createGraphics2D(fontInfo, validator); svg.paint(g2d); @@ -56,10 +62,12 @@ abstract class NativeTextPainterTest { return fontInfo; } - private BridgeContext createBridgeContext(FontInfo fontInfo) { + private BridgeContext createBridgeContext(FontInfo fontInfo, int sourceResolution) { FOUserAgent userAgent = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent(); SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new FOPFontFamilyResolverImpl(fontInfo), new AffineTransform()); + svgUserAgent.setSourceResolution(sourceResolution); + BridgeContext bridgeContext = new BridgeContext(svgUserAgent); bridgeContext.setTextPainter(createTextPainter(fontInfo)); return bridgeContext; diff --git a/fop-core/src/test/java/org/apache/fop/svg/SimpleSVGUserAgentTestCase.java b/fop-core/src/test/java/org/apache/fop/svg/SimpleSVGUserAgentTestCase.java new file mode 100644 index 000000000..2d9ae9285 --- /dev/null +++ b/fop-core/src/test/java/org/apache/fop/svg/SimpleSVGUserAgentTestCase.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.fop.svg; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SimpleSVGUserAgentTestCase { + + @Test + public void testMediumFontResolution72() { + checkGetMediumFontSize(72f, 12f); + } + + @Test + public void testMediumFontResolution96() { + checkGetMediumFontSize(96f, 16f); + } + + private void checkGetMediumFontSize(float sourceRes, float expectedSize) { + SimpleSVGUserAgent adapter = new SimpleSVGUserAgent(null, null, sourceRes); + + // Size must be calculated based on the dpi settings + assertEquals(expectedSize, adapter.getMediumFontSize(), 0.01); + } +}