]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
FOP-3135: SVG tspan content is displayed out of place by João André Gonçalves
authorSimon Steiner <ssteiner@apache.org>
Mon, 15 Jul 2024 12:10:58 +0000 (13:10 +0100)
committerSimon Steiner <ssteiner@apache.org>
Mon, 15 Jul 2024 12:10:58 +0000 (13:10 +0100)
fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
fop-core/src/main/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java
fop-core/src/main/java/org/apache/fop/image/loader/batik/PreloaderSVG.java
fop-core/src/main/java/org/apache/fop/svg/AbstractFOPTranscoder.java
fop-core/src/main/java/org/apache/fop/svg/SVGUserAgent.java
fop-core/src/main/java/org/apache/fop/svg/SimpleSVGUserAgent.java
fop-core/src/test/java/org/apache/fop/svg/NativeTextPainterTest.java
fop-core/src/test/java/org/apache/fop/svg/SimpleSVGUserAgentTestCase.java [new file with mode: 0644]

index 9fec79bf4b27bee552536f6d79bcbe8372e53944..443b020287830e8045ad94bda14d6db2c77394b2 100644 (file)
@@ -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);
             }
index b5d8626f9a7d0a35d3c5863ca1b497446543a765..02f1d68712a95e86b70854bec42037c5a8bf53ca 100644 (file)
@@ -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
index 7df9a6cb69aec07c223c4d78ccad653df532167d..4d8f6d123a280e86341ca104f7e0834fc5a61aa9 100644 (file)
@@ -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) {
index 0b3e6985f5b46469187e0b9183a6e099515384a1..2aca0cd96ab425248303d0f3aa3ba4017962a86c 100644 (file)
@@ -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;
             }
         }
 
index 6a4d9d0de81398b79b859dac49939ce30996af8a..01d6e487c2667749699f06982bcb59db0dcf1e6a 100644 (file)
@@ -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());
     }
 
index 0267cb6837f878faf6a8bfc26f4458932dbdca7e..d4075c73bb8132b38fe8731ae0df2ac8e65f164c 100644 (file)
@@ -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());
     }
 
     /**
index aa3019c9ced23eb19fae0aa76965d1470833c161..1890e4c670e0af01c4e998005e743735166d687b 100644 (file)
@@ -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 (file)
index 0000000..2d9ae92
--- /dev/null
@@ -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);
+    }
+}