FOP-2994: Support OTF/TTF SVG fonts

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1885366 13f79535-47bb-0310-9956-ffa450edef68
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 ffb92b0..159efe4 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
@@ -413,7 +413,7 @@
         try {
             // Have to do this so we can resolve data URIs
             StreamSource src = new StreamSource(resourceResolver.getResource(uri));
-            src.setSystemId(uri);
+            src.setSystemId(getResourceResolver().getBaseURI().toASCIIString());
             return src;
         } catch (URISyntaxException use) {
             return null;
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
index f125dc6..642b76f 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
@@ -141,7 +141,7 @@
      */
     public FopConfParser(File fopConfFile, ResourceResolver resourceResolver)
             throws SAXException, IOException {
-        this(new FileInputStream(fopConfFile), fopConfFile.toURI(), resourceResolver);
+        this(new FileInputStream(fopConfFile), fopConfFile.getParentFile().toURI(), resourceResolver);
     }
 
     public FopConfParser(InputStream fopConfStream, URI baseURI, EnvironmentProfile enviro)
diff --git a/fop-core/src/main/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java b/fop-core/src/main/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java
index 4b319f1..0607f99 100644
--- a/fop-core/src/main/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java
+++ b/fop-core/src/main/java/org/apache/fop/complexscripts/fonts/OTFAdvancedTypographicTableReader.java
@@ -215,7 +215,9 @@
                 log.debug(tableTag + " lang sys default: " + dt);
             }
         }
-        seScripts.put(scriptTag, new Object[] { dt, ll, seLanguages });
+        if (seLanguages != null) {
+            seScripts.put(scriptTag, new Object[]{dt, ll, seLanguages});
+        }
         seLanguages = null;
     }
 
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/CustomFont.java b/fop-core/src/main/java/org/apache/fop/fonts/CustomFont.java
index 2b659f5..cd026e1 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/CustomFont.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/CustomFont.java
@@ -32,6 +32,7 @@
 import java.util.Set;
 
 import org.apache.fop.apps.io.InternalResourceResolver;
+import org.apache.fop.fonts.truetype.SVGGlyphData;
 
 
 /**
@@ -80,6 +81,7 @@
     private boolean useKerning = true;
     /** the character map, mapping Unicode ranges to glyph indices. */
     protected List<CMapSegment> cmap = new ArrayList<CMapSegment>();
+    protected Map<Integer, SVGGlyphData> svgs;
     private boolean useAdvanced = true;
     private boolean simulateStyle;
     protected List<SimpleSingleByteEncoding> additionalEncodings;
@@ -682,4 +684,12 @@
         }
         return 0;
     }
+
+    public boolean hasSVG() {
+        return svgs != null;
+    }
+
+    public void setSVG(Map<Integer, SVGGlyphData> svgs) {
+        this.svgs = svgs;
+    }
 }
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfig.java b/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfig.java
index a166375..2b67dbd 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfig.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfig.java
@@ -132,7 +132,8 @@
                         fontCfg.getAttribute("encoding-mode", EncodingMode.AUTO.getName()),
                         fontCfg.getAttribute("embedding-mode", EncodingMode.AUTO.getName()),
                         fontCfg.getAttributeAsBoolean("simulate-style", false),
-                        fontCfg.getAttributeAsBoolean("embed-as-type1", false));
+                        fontCfg.getAttributeAsBoolean("embed-as-type1", false),
+                        fontCfg.getAttributeAsBoolean("svg", true));
                 instance.fonts.add(font);
                 boolean hasTriplets = false;
                 for (Configuration tripletCfg : fontCfg.getChildren("font-triplet")) {
@@ -322,6 +323,8 @@
         private final boolean embedAsType1;
         private final boolean simulateStyle;
 
+        private final boolean useSVG;
+
         private final List<FontTriplet> tripletList = new ArrayList<FontTriplet>();
 
         public List<FontTriplet> getTripletList() {
@@ -330,7 +333,7 @@
 
         private Font(String metrics, String embed, String afm, String pfm, String subFont, boolean kerning,
                      boolean advanced, String encodingMode, String embeddingMode, boolean simulateStyle,
-                     boolean embedAsType1) {
+                     boolean embedAsType1, boolean useSVG) {
             this.metrics = metrics;
             this.embedUri = embed;
             this.afm = afm;
@@ -342,6 +345,7 @@
             this.embeddingMode = embeddingMode;
             this.simulateStyle = simulateStyle;
             this.embedAsType1 = embedAsType1;
+            this.useSVG = useSVG;
         }
 
         /**
@@ -399,5 +403,9 @@
         public boolean getEmbedAsType1() {
             return embedAsType1;
         }
+
+        public boolean getUseSVG() {
+            return useSVG;
+        }
     }
 }
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfigurator.java b/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfigurator.java
index c8d1c00..6e8c493 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfigurator.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/DefaultFontConfigurator.java
@@ -168,7 +168,7 @@
         EmbeddingMode embeddingMode = EmbeddingMode.getValue(font.getEmbeddingMode());
         EmbedFontInfo embedFontInfo = new EmbedFontInfo(fontUris, font.isKerning(),
                 font.isAdvanced(), tripletList, subFont, encodingMode, embeddingMode,
-                font.getSimulateStyle(), font.getEmbedAsType1());
+                font.getSimulateStyle(), font.getEmbedAsType1(), font.getUseSVG());
         if (fontCache != null) {
             if (!fontCache.containsFont(embedFontInfo)) {
                 fontCache.addFont(embedFontInfo, resourceResolver);
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/EmbedFontInfo.java b/fop-core/src/main/java/org/apache/fop/fonts/EmbedFontInfo.java
index 186f098..27a0a4d 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/EmbedFontInfo.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/EmbedFontInfo.java
@@ -45,6 +45,7 @@
     /** simulates bold or italic on a regular font */
     private final boolean simulateStyle;
     private final boolean embedAsType1;
+    private final boolean useSVG;
 
     /** the PostScript name of the font */
     protected String postScriptName;
@@ -69,7 +70,7 @@
      */
     public EmbedFontInfo(FontUris fontUris, boolean kerning, boolean advanced,
             List<FontTriplet> fontTriplets, String subFontName, EncodingMode encodingMode,
-            EmbeddingMode embeddingMode, boolean simulateStyle, boolean embedAsType1) {
+            EmbeddingMode embeddingMode, boolean simulateStyle, boolean embedAsType1, boolean useSVG) {
         this.kerning = kerning;
         this.advanced = advanced;
         this.fontTriplets = fontTriplets;
@@ -79,6 +80,7 @@
         this.fontUris = fontUris;
         this.simulateStyle = simulateStyle;
         this.embedAsType1 = embedAsType1;
+        this.useSVG = useSVG;
     }
 
     /**
@@ -91,7 +93,7 @@
     public EmbedFontInfo(FontUris fontUris, boolean kerning, boolean advanced,
             List<FontTriplet> fontTriplets, String subFontName) {
         this(fontUris, kerning, advanced, fontTriplets, subFontName, EncodingMode.AUTO,
-                EmbeddingMode.AUTO, false, false);
+                EmbeddingMode.AUTO, false, false, true);
     }
 
     /**
@@ -209,6 +211,10 @@
         return embedAsType1;
     }
 
+    public boolean getUseSVG() {
+        return useSVG;
+    }
+
     private void readObject(java.io.ObjectInputStream in)
                 throws IOException, ClassNotFoundException {
         in.defaultReadObject();
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/FontLoader.java b/fop-core/src/main/java/org/apache/fop/fonts/FontLoader.java
index 06907f4..1e3d409 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/FontLoader.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/FontLoader.java
@@ -93,7 +93,7 @@
     public static CustomFont loadFont(FontUris fontUris, String subFontName,
             boolean embedded, EmbeddingMode embeddingMode, EncodingMode encodingMode,
             boolean useKerning, boolean useAdvanced, InternalResourceResolver resourceResolver,
-            boolean simulateStyle, boolean embedAsType1) throws IOException {
+            boolean simulateStyle, boolean embedAsType1, boolean useSVG) throws IOException {
         boolean type1 = isType1(fontUris);
         FontLoader loader;
         if (type1) {
@@ -105,7 +105,7 @@
                     resourceResolver);
         } else {
             loader = new OFFontLoader(fontUris.getEmbed(), subFontName, embedded, embeddingMode,
-                    encodingMode, useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1);
+                    encodingMode, useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1, useSVG);
         }
         return loader.getFont();
     }
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/LazyFont.java b/fop-core/src/main/java/org/apache/fop/fonts/LazyFont.java
index 7b2d465..753cece 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/LazyFont.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/LazyFont.java
@@ -47,6 +47,7 @@
     private final boolean useAdvanced;
     private boolean simulateStyle;
     private boolean embedAsType1;
+    private boolean useSVG;
     private final EncodingMode encodingMode;
     private final EmbeddingMode embeddingMode;
     private final String subFontName;
@@ -74,6 +75,7 @@
         }
         this.simulateStyle = fontInfo.getSimulateStyle();
         this.embedAsType1 = fontInfo.getEmbedAsType1();
+        useSVG = fontInfo.getUseSVG();
         this.encodingMode = fontInfo.getEncodingMode() != null ? fontInfo.getEncodingMode()
                 : EncodingMode.AUTO;
         this.embeddingMode = fontInfo.getEmbeddingMode() != null ? fontInfo.getEmbeddingMode()
@@ -116,8 +118,8 @@
                     if (fontUris.getEmbed() == null) {
                         throw new RuntimeException("Cannot load font. No font URIs available.");
                     }
-                    realFont = FontLoader.loadFont(fontUris, subFontName, embedded, embeddingMode,
-                                encodingMode, useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1);
+                    realFont = FontLoader.loadFont(fontUris, subFontName, embedded, embeddingMode, encodingMode,
+                            useKerning, useAdvanced, resourceResolver, simulateStyle, embedAsType1, useSVG);
                 }
                 if (realFont instanceof FontDescriptor) {
                     realFontDescriptor = (FontDescriptor) realFont;
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/MultiByteFont.java b/fop-core/src/main/java/org/apache/fop/fonts/MultiByteFont.java
index 3fd780d..4f1263e 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/MultiByteFont.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/MultiByteFont.java
@@ -42,6 +42,7 @@
 import org.apache.fop.complexscripts.util.CharAssociation;
 import org.apache.fop.complexscripts.util.CharNormalize;
 import org.apache.fop.complexscripts.util.GlyphSequence;
+import org.apache.fop.fonts.truetype.SVGGlyphData;
 import org.apache.fop.util.CharUtilities;
 
 /**
@@ -857,5 +858,10 @@
     public InputStream getCmapStream() {
         return null;
     }
+
+    public SVGGlyphData getSVG(char c) {
+        int gid = findGlyphIndex(c);
+        return svgs.get(gid);
+    }
 }
 
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/fop-core/src/main/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
index e14bb01..9e8d9e5 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
@@ -223,7 +223,7 @@
                 try {
                     OFFontLoader ttfLoader = new OFFontLoader(fontURI, fontName, true,
                             EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useAdvanced,
-                            resourceResolver, false, false);
+                            resourceResolver, false, false, true);
                     customFont = ttfLoader.getFont();
                     if (this.eventListener != null) {
                         customFont.setEventListener(this.eventListener);
@@ -251,7 +251,7 @@
             try {
                 FontUris fontUris = new FontUris(fontURI, null);
                 customFont = FontLoader.loadFont(fontUris, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO,
-                        useKerning, useAdvanced, resourceResolver, false, false);
+                        useKerning, useAdvanced, resourceResolver, false, false, true);
                 if (this.eventListener != null) {
                     customFont.setEventListener(this.eventListener);
                 }
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java
index 0634957..895b798 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java
@@ -55,6 +55,7 @@
     private EmbeddingMode embeddingMode;
     private boolean simulateStyle;
     private boolean embedAsType1;
+    private boolean useSVG;
 
     /**
      * Default constructor
@@ -63,7 +64,7 @@
      */
     public OFFontLoader(URI fontFileURI, InternalResourceResolver resourceResolver) {
         this(fontFileURI, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO, true, true, resourceResolver, false,
-                false);
+                false, true);
     }
 
     /**
@@ -79,15 +80,16 @@
      * @param resolver the FontResolver for font URI resolution
      * @param simulateStyle Determines whether to simulate font styles if a font does not support those by default.
      */
-    public OFFontLoader(URI fontFileURI, String subFontName, boolean embedded,
-            EmbeddingMode embeddingMode, EncodingMode encodingMode, boolean useKerning,
-            boolean useAdvanced, InternalResourceResolver resolver, boolean simulateStyle, boolean embedAsType1) {
+    public OFFontLoader(URI fontFileURI, String subFontName, boolean embedded, EmbeddingMode embeddingMode,
+        EncodingMode encodingMode, boolean useKerning, boolean useAdvanced, InternalResourceResolver resolver,
+        boolean simulateStyle, boolean embedAsType1, boolean useSVG) {
         super(fontFileURI, embedded, useKerning, useAdvanced, resolver);
         this.subFontName = subFontName;
         this.encodingMode = encodingMode;
         this.embeddingMode = embeddingMode;
         this.simulateStyle = simulateStyle;
         this.embedAsType1 = embedAsType1;
+        this.useSVG = useSVG;
         if (this.encodingMode == EncodingMode.AUTO) {
             this.encodingMode = EncodingMode.CID; //Default to CID mode for TrueType
         }
@@ -118,7 +120,7 @@
             if (!supported) {
                 throw new IOException("The font does not have a Unicode cmap table: " + fontFileURI);
             }
-            buildFont(otf, ttcFontName, embedAsType1);
+            buildFont(otf, ttcFontName);
             loaded = true;
         } finally {
             IOUtils.closeQuietly(in);
@@ -133,7 +135,7 @@
         return null;
     }
 
-    private void buildFont(OpenFont otf, String ttcFontName, boolean embedAsType1) {
+    private void buildFont(OpenFont otf, String ttcFontName) {
         boolean isCid = this.embedded;
         if (this.encodingMode == EncodingMode.SINGLE_BYTE) {
             isCid = false;
@@ -201,6 +203,9 @@
             copyGlyphMetricsSingleByte(otf);
         }
         returnFont.setCMap(getCMap(otf));
+        if (useSVG) {
+            returnFont.setSVG(otf.svgs);
+        }
 
         if (otf.getKerning() != null && useKerning) {
             copyKerning(otf, isCid);
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFTableName.java b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFTableName.java
index f626412..29d0f78 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFTableName.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFTableName.java
@@ -119,6 +119,8 @@
     /** Vertical Metrics. */
     public static final OFTableName VMTX = new OFTableName("vmtx");
 
+    public static final OFTableName SVG = new OFTableName("SVG ");
+
     private final String name;
 
     private OFTableName(String name) {
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OpenFont.java b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OpenFont.java
index 5076e30..0d10129 100644
--- a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OpenFont.java
+++ b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OpenFont.java
@@ -31,6 +31,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -219,6 +220,7 @@
 
     private int[] ansiWidth;
     private Map<Integer, List<Integer>> ansiIndex;
+    protected Map<Integer, SVGGlyphData> svgs;
 
     // internal mapping of glyph indexes to unicode indexes
     // used for quick mappings in this class
@@ -839,6 +841,7 @@
         readPostScript();
         readOS2();
         determineAscDesc();
+        readSVG();
 
         readName();
         boolean pcltFound = readPCLT();
@@ -1329,6 +1332,33 @@
         }
     }
 
+    private void readSVG() throws IOException {
+        OFDirTabEntry dirTab = dirTabs.get(OFTableName.SVG);
+        if (dirTab != null) {
+            svgs = new LinkedHashMap<>();
+            fontFile.seekSet(dirTab.getOffset());
+            fontFile.readTTFUShort(); //version
+            fontFile.readTTFULong(); //svgDocumentListOffset
+            fontFile.readTTFULong(); //reserved
+            int numEntries = fontFile.readTTFUShort();
+            for (int i = 0; i < numEntries; i++) {
+                int startGlyphID = fontFile.readTTFUShort();
+                fontFile.readTTFUShort(); //endGlyphID
+                SVGGlyphData svgGlyph = new SVGGlyphData();
+                svgGlyph.svgDocOffset = fontFile.readTTFULong();
+                svgGlyph.svgDocLength = fontFile.readTTFULong();
+                svgs.put(startGlyphID, svgGlyph);
+            }
+            for (SVGGlyphData entry : svgs.values()) {
+                seekTab(fontFile, OFTableName.SVG, entry.svgDocOffset);
+                fontFile.readTTFUShort(); //version
+                fontFile.readTTFULong(); //svgDocumentListOffset
+                fontFile.readTTFULong(); //reserved
+                entry.setSVG(fontFile.readTTFString((int) entry.svgDocLength));
+            }
+        }
+    }
+
     /**
      * Read "hmtx" table and put the horizontal metrics
      * in the mtxTab array. If the number of metrics is less
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/truetype/SVGGlyphData.java b/fop-core/src/main/java/org/apache/fop/fonts/truetype/SVGGlyphData.java
new file mode 100644
index 0000000..e46e500
--- /dev/null
+++ b/fop-core/src/main/java/org/apache/fop/fonts/truetype/SVGGlyphData.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/* $Id$ */
+package org.apache.fop.fonts.truetype;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import org.apache.xmlgraphics.util.uri.DataURLUtil;
+
+public class SVGGlyphData {
+    protected long svgDocOffset;
+    protected long svgDocLength;
+    private String svg;
+    public float scale = 1;
+
+    public void setSVG(String svg) {
+        this.svg = svg;
+    }
+
+    public String getDataURL(int height) {
+        try {
+            String modifiedSVG = updateTransform(svg, height);
+            return DataURLUtil.createDataURL(new ByteArrayInputStream(modifiedSVG.getBytes("UTF-8")), "image/svg");
+        } catch (IOException | TransformerException | SAXException | ParserConfigurationException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private String updateTransform(String svg, int height)
+            throws IOException, ParserConfigurationException, SAXException, TransformerException {
+        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        InputSource inputSource = new InputSource();
+        inputSource.setCharacterStream(new StringReader(svg));
+        Document doc = documentBuilder.parse(inputSource);
+        NodeList nodes = doc.getElementsByTagName("g");
+        Element gElement = (Element) nodes.item(0);
+        if (gElement != null) {
+            String transform = gElement.getAttribute("transform");
+            if (transform.contains("scale(")) {
+                String scaleStr = transform.split("scale\\(")[1].split("\\)")[0].trim();
+                scale = Float.parseFloat(scaleStr);
+                gElement.removeAttribute("transform");
+            } else {
+                gElement.setAttribute("transform", "translate(0," + height + ")");
+            }
+        } else {
+            Element svgElement = (Element) doc.getElementsByTagName("svg").item(0);
+            svgElement.setAttribute("viewBox", "0 0 1000 " + height);
+            gElement = doc.createElement("g");
+            gElement.setAttribute("transform", "translate(0," + height + ")");
+            NodeList paths = doc.getElementsByTagName("path");
+            for (int i = 0; i < paths.getLength(); i++) {
+                Node path = paths.item(i);
+                if (i == 0) {
+                    path.getParentNode().insertBefore(gElement, path);
+                }
+                gElement.appendChild(path);
+            }
+        }
+        Transformer transformer = TransformerFactory.newInstance().newTransformer();
+        StreamResult result = new StreamResult(new StringWriter());
+        DOMSource source = new DOMSource(doc);
+        transformer.transform(source, result);
+        return result.getWriter().toString();
+    }
+}
diff --git a/fop-core/src/main/java/org/apache/fop/render/afp/AFPFontConfig.java b/fop-core/src/main/java/org/apache/fop/render/afp/AFPFontConfig.java
index 0967bd1..eb6c4a7 100644
--- a/fop-core/src/main/java/org/apache/fop/render/afp/AFPFontConfig.java
+++ b/fop-core/src/main/java/org/apache/fop/render/afp/AFPFontConfig.java
@@ -384,7 +384,7 @@
             try {
                 FontUris fontUris = new FontUris(new URI(fontUri), null);
                 EmbedFontInfo embedFontInfo = new EmbedFontInfo(fontUris, false, true, null, subfont, EncodingMode.AUTO,
-                        EmbeddingMode.FULL, false, false);
+                        EmbeddingMode.FULL, false, false, true);
                 Typeface tf = new LazyFont(embedFontInfo, resourceResolver, false).getRealFont();
                 AFPResourceAccessor accessor = getAccessor(resourceResolver);
                 CharacterSet characterSet = CharacterSetBuilder.getDoubleByteInstance().build(characterset,
diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
index 45996a2..44620ff 100644
--- a/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
@@ -46,8 +46,11 @@
 import org.apache.fop.ResourceEventProducer;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.fo.Constants;
+import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.truetype.SVGGlyphData;
 import org.apache.fop.render.ImageHandler;
 import org.apache.fop.render.ImageHandlerRegistry;
 import org.apache.fop.render.ImageHandlerUtil;
@@ -469,4 +472,25 @@
                          int[][] dp, String text, boolean nextIsSpace) throws IFException {
         drawText(x, y, letterSpacing, wordSpacing, dp, text);
     }
+
+    protected void drawSVGText(MultiByteFont multiByteFont, FontTriplet triplet, int x, int y, String text,
+                               IFState state) throws IFException {
+        int sizeMillipoints = state.getFontSize();
+        Font font = getFontInfo().getFontInstance(triplet, sizeMillipoints);
+        int newx = x;
+        for (char c : text.toCharArray()) {
+            SVGGlyphData svg = multiByteFont.getSVG(c);
+            if (svg != null) {
+                int codePoint = font.mapCodePoint(c);
+                String dataURL = svg.getDataURL(multiByteFont.getCapHeight());
+                Rectangle boundingBox = multiByteFont.getBoundingBox(codePoint, (int) (sizeMillipoints / 1000f));
+                boundingBox.y = y - boundingBox.height - boundingBox.y;
+                boundingBox.x = newx;
+                boundingBox.width = (int) (sizeMillipoints * svg.scale);
+                boundingBox.height = (int) (sizeMillipoints * svg.scale);
+                drawImage(dataURL, boundingBox);
+            }
+            newx += font.getCharWidth(c);
+        }
+    }
 }
diff --git a/fop-core/src/main/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java b/fop-core/src/main/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java
index e494ed6..d019f35 100644
--- a/fop-core/src/main/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java
+++ b/fop-core/src/main/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java
@@ -83,11 +83,11 @@
                     font = new CustomFontMetricsMapper(fontMetrics, fontSource);
                 } else {
                     FontUris fontUris = configFontInfo.getFontUris();
-                    CustomFont fontMetrics = FontLoader.loadFont(fontUris,
-                            configFontInfo.getSubFontName(), true,
+                    CustomFont fontMetrics = FontLoader.loadFont(fontUris, configFontInfo.getSubFontName(), true,
                             configFontInfo.getEmbeddingMode(), configFontInfo.getEncodingMode(),
                             configFontInfo.getKerning(), configFontInfo.getAdvanced(), resourceResolver,
-                            configFontInfo.getSimulateStyle(), configFontInfo.getEmbedAsType1());
+                            configFontInfo.getSimulateStyle(), configFontInfo.getEmbedAsType1(),
+                            configFontInfo.getUseSVG());
                     font = new CustomFontMetricsMapper(fontMetrics);
                 }
 
diff --git a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java
index 985e587..cae8973 100644
--- a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java
@@ -43,6 +43,7 @@
 import org.apache.fop.fonts.Font;
 import org.apache.fop.fonts.FontTriplet;
 import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.MultiByteFont;
 import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.pdf.PDFArray;
@@ -431,8 +432,11 @@
 
         FontTriplet triplet = new FontTriplet(
                 state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
-
-        if ((dp == null) || IFUtil.isDPOnlyDX(dp)) {
+        String fontKey = getFontInfo().getInternalFontKey(triplet);
+        Typeface typeface = getTypeface(fontKey);
+        if (typeface instanceof MultiByteFont && ((MultiByteFont) typeface).hasSVG()) {
+            drawSVGText((MultiByteFont) typeface, triplet, x, y, text, state);
+        } else if ((dp == null) || IFUtil.isDPOnlyDX(dp)) {
             drawTextWithDX(x, y, text, triplet, letterSpacing,
                              wordSpacing, IFUtil.convertDPToDX(dp));
         } else {
diff --git a/fop-core/src/main/java/org/apache/fop/render/ps/PSImageHandlerSVG.java b/fop-core/src/main/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
index b034fa7..9c0a902 100644
--- a/fop-core/src/main/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
+++ b/fop-core/src/main/java/org/apache/fop/render/ps/PSImageHandlerSVG.java
@@ -21,6 +21,7 @@
 
 import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.Graphics2D;
 import java.awt.Rectangle;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
@@ -43,14 +44,11 @@
 import org.apache.batik.bridge.BridgeContext;
 import org.apache.batik.bridge.GVTBuilder;
 import org.apache.batik.gvt.GraphicsNode;
-import org.apache.batik.transcoder.SVGAbstractTranscoder;
-import org.apache.batik.transcoder.TranscoderException;
-import org.apache.batik.transcoder.TranscoderInput;
-import org.apache.batik.transcoder.TranscoderOutput;
-import org.apache.batik.transcoder.image.PNGTranscoder;
 
 import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageException;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
 import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
 import org.apache.xmlgraphics.ps.ImageEncoder;
 import org.apache.xmlgraphics.ps.ImageEncodingHelper;
@@ -58,6 +56,7 @@
 
 import org.apache.fop.image.loader.batik.BatikImageFlavors;
 import org.apache.fop.image.loader.batik.BatikUtil;
+import org.apache.fop.image.loader.batik.ImageConverterSVG2G2D;
 import org.apache.fop.render.ImageHandler;
 import org.apache.fop.render.RenderingContext;
 import org.apache.fop.render.ps.svg.PSSVGGraphics2D;
@@ -85,7 +84,7 @@
         ImageXMLDOM imageSVG = (ImageXMLDOM)image;
 
         if (shouldRaster(imageSVG)) {
-            InputStream is = renderSVGToInputStream(context, imageSVG);
+            InputStream is = renderSVGToInputStream(imageSVG, pos);
 
             float x = (float) pos.getX() / 1000f;
             float y = (float) pos.getY() / 1000f;
@@ -175,25 +174,35 @@
         }
     }
 
-    private InputStream renderSVGToInputStream(RenderingContext context, ImageXMLDOM imageSVG) throws IOException {
-        PNGTranscoder png = new PNGTranscoder();
-        Float width = getDimension(imageSVG.getDocument(), "width") * 8;
-        png.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, width);
-        Float height = getDimension(imageSVG.getDocument(), "height") * 8;
-        png.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, height);
-        TranscoderInput input = new TranscoderInput(imageSVG.getDocument());
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        TranscoderOutput output = new TranscoderOutput(os);
-        try {
-            png.transcode(input, output);
-        } catch (TranscoderException ex) {
-            SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
-                    context.getUserAgent().getEventBroadcaster());
-            eventProducer.svgRenderingError(this, ex, imageSVG.getInfo().getOriginalURI());
-        } finally {
-            os.flush();
-            os.close();
+    private InputStream renderSVGToInputStream(ImageXMLDOM imageSVG, Rectangle destinationRect)
+        throws IOException {
+        Rectangle rectangle;
+        int width;
+        int height;
+        Float widthSVG = getDimension(imageSVG.getDocument(), "width");
+        Float heightSVG = getDimension(imageSVG.getDocument(), "height");
+        if (widthSVG != null && heightSVG != null) {
+            width = (int) (widthSVG * 8);
+            height = (int) (heightSVG * 8);
+            rectangle = new Rectangle(0, 0, width, height);
+        } else {
+            int scale = 10;
+            width = destinationRect.width / scale;
+            height = destinationRect.height / scale;
+            rectangle = new Rectangle(0, 0, destinationRect.width / 100, destinationRect.height / 100);
+            destinationRect.width *= scale;
+            destinationRect.height *= scale;
         }
+        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D graphics2D = image.createGraphics();
+        try {
+            ImageGraphics2D img = (ImageGraphics2D) new ImageConverterSVG2G2D().convert(imageSVG, new HashMap());
+            img.getGraphics2DImagePainter().paint(graphics2D, rectangle);
+        } catch (ImageException e) {
+            throw new IOException(e);
+        }
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        ImageIO.write(image, "png", os);
         return new ByteArrayInputStream(os.toByteArray());
     }
 
diff --git a/fop-core/src/main/java/org/apache/fop/render/ps/PSPainter.java b/fop-core/src/main/java/org/apache/fop/render/ps/PSPainter.java
index 34f57e4..a7f0f45 100644
--- a/fop-core/src/main/java/org/apache/fop/render/ps/PSPainter.java
+++ b/fop-core/src/main/java/org/apache/fop/render/ps/PSPainter.java
@@ -359,25 +359,28 @@
             }
             PSGenerator generator = getGenerator();
             generator.useColor(state.getTextColor());
+            FontTriplet triplet = new FontTriplet(state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
+            String fontKey = getFontKey(triplet);
+            Typeface typeface = getTypeface(fontKey);
+            if (typeface instanceof MultiByteFont && ((MultiByteFont) typeface).hasSVG()) {
+                drawSVGText((MultiByteFont) typeface, triplet, x, y, text, state);
+                return;
+            }
             beginTextObject();
-            FontTriplet triplet = new FontTriplet(
-                    state.getFontFamily(), state.getFontStyle(), state.getFontWeight());
             //TODO Ignored: state.getFontVariant()
             //TODO Opportunity for font caching if font state is more heavily used
-            String fontKey = getFontKey(triplet);
             int sizeMillipoints = state.getFontSize();
 
             // This assumes that *all* CIDFonts use a /ToUnicode mapping
-            Typeface tf = getTypeface(fontKey);
             SingleByteFont singleByteFont = null;
-            if (tf instanceof SingleByteFont) {
-                singleByteFont = (SingleByteFont)tf;
+            if (typeface instanceof SingleByteFont) {
+                singleByteFont = (SingleByteFont)typeface;
             }
             Font font = getFontInfo().getFontInstance(triplet, sizeMillipoints);
 
             PSFontResource res = getDocumentHandler().getPSResourceForFontKey(fontKey);
-            boolean otf = tf instanceof MultiByteFont && ((MultiByteFont)tf).isOTFFile();
-            useFont(fontKey, sizeMillipoints, otf);
+            boolean isOpenTypeFont = typeface instanceof MultiByteFont && ((MultiByteFont)typeface).isOTFFile();
+            useFont(fontKey, sizeMillipoints, isOpenTypeFont);
 
             if (dp != null && dp[0] != null) {
                 x += dp[0][0];
@@ -393,12 +396,12 @@
                 int currentEncoding = -1;
                 for (int i = 0; i < textLen; i++) {
                     char c = text.charAt(i);
-                    char mapped = tf.mapChar(c);
+                    char mapped = typeface.mapChar(c);
                     int encoding = mapped / 256;
                     if (currentEncoding != encoding) {
                         if (i > 0) {
                             writeText(text, start, i - start,
-                                    letterSpacing, wordSpacing, dp, font, tf, false);
+                                    letterSpacing, wordSpacing, dp, font, typeface, false);
                         }
                         if (encoding == 0) {
                             useFont(fontKey, sizeMillipoints, false);
@@ -410,20 +413,20 @@
                     }
                 }
             } else {
-                if (tf instanceof MultiByteFont && ((MultiByteFont)tf).isOTFFile()) {
+                if (typeface instanceof MultiByteFont && ((MultiByteFont)typeface).isOTFFile()) {
                     //Analyze string and split up in order to paint in different sub-fonts/encodings
                     int curEncoding = 0;
                     for (int i = start; i < textLen; i++) {
                         char orgChar = text.charAt(i);
 
-                        MultiByteFont mbFont = (MultiByteFont)tf;
+                        MultiByteFont mbFont = (MultiByteFont)typeface;
                         mbFont.mapChar(orgChar);
                         int origGlyphIdx = mbFont.findGlyphIndex(orgChar);
                         int newGlyphIdx = mbFont.getUsedGlyphs().get(origGlyphIdx);
                         int encoding = newGlyphIdx / 256;
                         if (encoding != curEncoding) {
                             if (i != 0) {
-                                writeText(text, start, i - start, letterSpacing, wordSpacing, dp, font, tf,
+                                writeText(text, start, i - start, letterSpacing, wordSpacing, dp, font, typeface,
                                         true);
                                 start = i;
                             }
@@ -435,8 +438,8 @@
                     useFont(fontKey, sizeMillipoints, false);
                 }
             }
-            writeText(text, start, textLen - start, letterSpacing, wordSpacing, dp, font, tf,
-                    tf instanceof MultiByteFont);
+            writeText(text, start, textLen - start, letterSpacing, wordSpacing, dp, font, typeface,
+                    typeface instanceof MultiByteFont);
         } catch (IOException ioe) {
             throw new IFException("I/O error in drawText()", ioe);
         }
diff --git a/fop-core/src/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java b/fop-core/src/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java
index f692a56..bf3da20 100644
--- a/fop-core/src/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/fonts/DejaVuLGCSerifTestCase.java
@@ -49,7 +49,7 @@
         File file = new File("test/resources/fonts/ttf/DejaVuLGCSerif.ttf");
         FontUris fontUris = new FontUris(file.toURI(), null);
         font = FontLoader.loadFont(fontUris, "", true, EmbeddingMode.AUTO, EncodingMode.AUTO,
-                false, false, resolver, false, false);
+                false, false, resolver, false, false, true);
     }
 
     /**
diff --git a/fop-core/src/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java b/fop-core/src/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java
index 9e0a7f1..2fb3665 100644
--- a/fop-core/src/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/fonts/EmbedFontInfoTestCase.java
@@ -54,7 +54,7 @@
         triplets.add(triplet);
         FontUris fontUris = new FontUris(embedURI, metricsURI);
         sut = new EmbedFontInfo(fontUris, kerning, useAdvanced, triplets, subFontName, encMode,
-                embedMode, false, false);
+                embedMode, false, false, true);
     }
 
     @Test
diff --git a/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java b/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java
index 9194d16..a3d8676 100644
--- a/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFToType1TestCase.java
@@ -78,7 +78,7 @@
         InternalResourceResolver rr = ResourceResolverFactory.createDefaultInternalResourceResolver(
                 new File(".").toURI());
         CustomFont realFont = FontLoader.loadFont(new FontUris(new File(s).toURI(), null), null, true,
-                EmbeddingMode.SUBSET, EncodingMode.AUTO, true, true, rr, false, true);
+                EmbeddingMode.SUBSET, EncodingMode.AUTO, true, true, rr, false, true, true);
         realFont.mapChar('d');
         return realFont;
     }
diff --git a/fop-core/src/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java b/fop-core/src/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java
index 5201edb..e291b8e 100644
--- a/fop-core/src/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/fonts/truetype/TTFFontLoaderTestCase.java
@@ -51,12 +51,12 @@
 
         OFFontLoader fontLoader = new OFFontLoader(absoluteFilePath, fontName, embedded,
                 EmbeddingMode.AUTO, EncodingMode.AUTO, useKerning, useComplexScriptFeatures,
-                resourceResolver, false, false);
+                resourceResolver, false, false, true);
         assertTrue(fontLoader.getFont().hasKerningInfo());
         useKerning = false;
 
         fontLoader = new OFFontLoader(absoluteFilePath, fontName, embedded, EmbeddingMode.AUTO,
-                EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resourceResolver, false, false);
+                EncodingMode.AUTO, useKerning, useComplexScriptFeatures, resourceResolver, false, false, true);
         assertFalse(fontLoader.getFont().hasKerningInfo());
     }
 }
diff --git a/fop-core/src/test/java/org/apache/fop/fonts/type1/Type1FontLoaderTestCase.java b/fop-core/src/test/java/org/apache/fop/fonts/type1/Type1FontLoaderTestCase.java
index 84b0b1a..db8d4a6 100644
--- a/fop-core/src/test/java/org/apache/fop/fonts/type1/Type1FontLoaderTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/fonts/type1/Type1FontLoaderTestCase.java
@@ -29,6 +29,7 @@
 
 import org.apache.commons.io.IOUtils;
 
+import org.apache.fop.apps.io.InternalResourceResolver;
 import org.apache.fop.apps.io.ResourceResolverFactory;
 import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.EmbeddingMode;
@@ -50,8 +51,10 @@
             fos.close();
 
             FontUris fontUris = new FontUris(pfbNoAFM.toURI(), null, null, pfm.toURI());
+            InternalResourceResolver resourceResolver =
+                    ResourceResolverFactory.createDefaultInternalResourceResolver(new File(".").toURI());
             CustomFont x = FontLoader.loadFont(fontUris, null, true, EmbeddingMode.AUTO, EncodingMode.AUTO, true, true,
-                    ResourceResolverFactory.createDefaultInternalResourceResolver(new File(".").toURI()), false, false);
+                    resourceResolver, false, false, true);
             Assert.assertEquals(x.getBoundingBox(0, 12).getBounds(), new Rectangle(-240, -60, 0, 60));
         } finally {
             pfbNoAFM.delete();
diff --git a/fop-core/src/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java b/fop-core/src/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java
index ddbe63e..f7f8e26 100644
--- a/fop-core/src/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/pdf/PDFFactoryTestCase.java
@@ -144,7 +144,7 @@
         PDFFactory pdfFactory = new PDFFactory(doc);
         URI uri = new File("test/resources/fonts/otf/SourceSansProBold.otf").toURI();
         CustomFont sb = OFFontLoader.loadFont(new FontUris(uri, null),
-                null, true, EmbeddingMode.SUBSET, null, false, false, rr, false, false);
+                null, true, EmbeddingMode.SUBSET, null, false, false, rr, false, false, true);
         for (char c = 0; c < 512; c++) {
             sb.mapChar(c);
         }
diff --git a/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java b/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java
index d0a29ab..aa0274d 100644
--- a/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/pdf/PDFPainterTestCase.java
@@ -25,7 +25,9 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.Locale;
+import java.util.Map;
 
 import javax.xml.transform.stream.StreamResult;
 
@@ -49,6 +51,7 @@
 import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.fonts.FontTriplet;
 import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.truetype.SVGGlyphData;
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFFilterList;
 import org.apache.fop.pdf.PDFPage;
@@ -305,4 +308,37 @@
                 + "\n"
                 + "endstream");
     }
+
+    @Test
+    public void testSVGFont() throws IFException, IOException {
+        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
+        foUserAgent = fopFactory.newFOUserAgent();
+        PDFDocumentHandler pdfDocumentHandler = new PDFDocumentHandler(new IFContext(foUserAgent));
+        pdfDocumentHandler.setResult(new StreamResult(new ByteArrayOutputStream()));
+        pdfDocumentHandler.startDocument();
+        pdfDocumentHandler.startPage(0, "", "", new Dimension());
+        FontInfo fi = new FontInfo();
+        fi.addFontProperties("f1", new FontTriplet("a", "normal", 400));
+        MultiByteFont font = new MultiByteFont(null, null);
+        font.setWidthArray(new int[1]);
+        Map<Integer, SVGGlyphData> svgs = new HashMap<>();
+        SVGGlyphData svgGlyph = new SVGGlyphData();
+        svgGlyph.setSVG("<svg xmlns=\"http://www.w3.org/2000/svg\">\n"
+                + "<circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"3\" fill=\"red\" />\n"
+                + "</svg>");
+        svgs.put(0, svgGlyph);
+        font.setSVG(svgs);
+        font.setBBoxArray(new Rectangle[] {new Rectangle()});
+        fi.addMetrics("f1", font);
+        pdfDocumentHandler.setFontInfo(fi);
+        PDFPainter pdfPainter = new PDFPainter(pdfDocumentHandler, null);
+        pdfPainter.setFont("a", "normal", 400, null, 12, null);
+        pdfPainter.drawText(0, 0, 0, 0, null, "test");
+        PDFFilterList filters = pdfPainter.generator.getStream().getFilterList();
+        filters.setDisableAllFilters(true);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        pdfPainter.generator.getStream().output(bos);
+        Assert.assertTrue(bos.toString().contains("0.00012 0 0 0.00012 0 0 cm"));
+        Assert.assertTrue(bos.toString().contains("1 0 0 rg"));
+    }
 }
diff --git a/fop-core/src/test/java/org/apache/fop/render/ps/PSPainterTestCase.java b/fop-core/src/test/java/org/apache/fop/render/ps/PSPainterTestCase.java
index 7cc0fd7..f575423 100644
--- a/fop-core/src/test/java/org/apache/fop/render/ps/PSPainterTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/render/ps/PSPainterTestCase.java
@@ -17,6 +17,7 @@
 package org.apache.fop.render.ps;
 
 import java.awt.Color;
+import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -54,6 +55,7 @@
 import org.apache.fop.fonts.FontTriplet;
 import org.apache.fop.fonts.MultiByteFont;
 import org.apache.fop.fonts.Typeface;
+import org.apache.fop.fonts.truetype.SVGGlyphData;
 import org.apache.fop.render.intermediate.IFContext;
 import org.apache.fop.render.intermediate.IFException;
 import org.apache.fop.render.intermediate.IFState;
@@ -242,4 +244,35 @@
         mbf.setIsOTFFile(otf);
         fi.addMetrics(name, mbf);
     }
+
+    @Test
+    public void testSVGFont() throws IFException {
+        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
+        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
+        PSDocumentHandler psDocumentHandler = new PSDocumentHandler(new IFContext(foUserAgent));
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        psDocumentHandler.setResult(new StreamResult(bos));
+        psDocumentHandler.startDocument();
+        psDocumentHandler.startPage(0, "", "", new Dimension());
+        FontInfo fi = new FontInfo();
+        fi.addFontProperties("f1", new FontTriplet("a", "normal", 400));
+        MultiByteFont font = new MultiByteFont(null, null);
+        font.setWidthArray(new int[1]);
+        Map<Integer, SVGGlyphData> svgs = new HashMap<>();
+        SVGGlyphData svgGlyph = new SVGGlyphData();
+        svgGlyph.setSVG("<svg xmlns=\"http://www.w3.org/2000/svg\">\n"
+                + "<circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"3\" fill=\"red\" />\n"
+                + "</svg>");
+        svgs.put(0, svgGlyph);
+        font.setSVG(svgs);
+        font.setBBoxArray(new Rectangle[] {new Rectangle()});
+        fi.addMetrics("f1", font);
+        psDocumentHandler.setFontInfo(fi);
+        PSPainter psPainter = new PSPainter(psDocumentHandler);
+        psPainter.setFont("a", "normal", 400, null, 12, Color.black);
+        psPainter.drawText(0, 0, 0, 0, null, "test");
+        Assert.assertTrue(bos.toString().contains("%FOPBeginSVG"));
+        Assert.assertTrue(bos.toString().contains("[0.00012 0 0 0.00012 0 0] CT"));
+        Assert.assertTrue(bos.toString().contains("1 0 0 RC"));
+    }
 }
diff --git a/fop-core/src/test/java/org/apache/fop/svg/font/FontInfoBuilder.java b/fop-core/src/test/java/org/apache/fop/svg/font/FontInfoBuilder.java
index 255bc19..57428fb 100644
--- a/fop-core/src/test/java/org/apache/fop/svg/font/FontInfoBuilder.java
+++ b/fop-core/src/test/java/org/apache/fop/svg/font/FontInfoBuilder.java
@@ -83,7 +83,7 @@
         URI baseURI = new File("test/resources/fonts/ttf").toURI();
         InternalResourceResolver resolver = ResourceResolverFactory.createDefaultInternalResourceResolver(baseURI);
         OFFontLoader fontLoader = new OFFontLoader(new URI(filename), null, true,
-                EmbeddingMode.AUTO, EncodingMode.AUTO, true, useAdvanced, resolver, false, false);
+                EmbeddingMode.AUTO, EncodingMode.AUTO, true, useAdvanced, resolver, false, false, true);
         FontMetrics font = fontLoader.getFont();
         registerFont(font, "F" + fontKey++, fontName);
         return this;