BATIK-1041: Make it possible to plug custom FontFamilyResolver


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/batik/branches/custom-FontFamilyResolver@1562794 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sources/org/apache/batik/bridge/BridgeContext.java b/sources/org/apache/batik/bridge/BridgeContext.java
index bef6a1d..a9011c3 100644
--- a/sources/org/apache/batik/bridge/BridgeContext.java
+++ b/sources/org/apache/batik/bridge/BridgeContext.java
@@ -58,6 +58,7 @@
 import org.apache.batik.gvt.CompositeGraphicsNode;
 import org.apache.batik.gvt.GraphicsNode;
 import org.apache.batik.gvt.TextPainter;
+import org.apache.batik.gvt.font.FontFamilyResolver;
 import org.apache.batik.script.Interpreter;
 import org.apache.batik.script.InterpreterPool;
 import org.apache.batik.util.CSSConstants;
@@ -281,6 +282,10 @@
      */
     protected BridgeContext() {}
 
+    public final FontFamilyResolver getFontFamilyResolver() {
+        return userAgent.getFontFamilyResolver();
+    }
+
     /**
      * Constructs a new bridge context.
      * @param userAgent the user agent
diff --git a/sources/org/apache/batik/bridge/FontFace.java b/sources/org/apache/batik/bridge/FontFace.java
index b4ff113..7fb3717 100644
--- a/sources/org/apache/batik/bridge/FontFace.java
+++ b/sources/org/apache/batik/bridge/FontFace.java
@@ -93,7 +93,8 @@
      * Returns the font associated with this rule or element.
      */
     public GVTFontFamily getFontFamily(BridgeContext ctx) {
-        String name = FontFamilyResolver.lookup(familyName);
+        final FontFamilyResolver fontFamilyResolver = ctx.getFontFamilyResolver();
+        String name = fontFamilyResolver.lookup(familyName);
         if (name != null) {
             GVTFontFace ff = createFontFace(name, this);
             return new AWTFontFamily(ff);
@@ -104,7 +105,7 @@
             Object o = iter.next();
             if (o instanceof String) {
                 String str = (String)o;
-                name = FontFamilyResolver.lookup(str);
+                name = fontFamilyResolver.lookup(str);
                 if (name != null) {
                     GVTFontFace ff = createFontFace(str, this);
                     return new AWTFontFamily(ff);
diff --git a/sources/org/apache/batik/bridge/SVGTextElementBridge.java b/sources/org/apache/batik/bridge/SVGTextElementBridge.java
index a0d281e..96defb3 100644
--- a/sources/org/apache/batik/bridge/SVGTextElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGTextElementBridge.java
@@ -29,8 +29,8 @@
 import java.awt.geom.Rectangle2D;
 import java.lang.ref.SoftReference;
 import java.text.AttributedCharacterIterator;
-import java.text.AttributedString;
 import java.text.AttributedCharacterIterator.Attribute;
+import java.text.AttributedString;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -61,7 +61,6 @@
 import org.apache.batik.dom.util.XMLSupport;
 import org.apache.batik.gvt.GraphicsNode;
 import org.apache.batik.gvt.TextNode;
-import org.apache.batik.gvt.font.FontFamilyResolver;
 import org.apache.batik.gvt.font.GVTFont;
 import org.apache.batik.gvt.font.GVTFontFamily;
 import org.apache.batik.gvt.font.GVTGlyphMetrics;
@@ -1521,21 +1520,17 @@
             Value it = val.item(i);
             String fontFamilyName = it.getStringValue();
             GVTFontFamily fontFamily;
-            fontFamily = SVGFontUtilities.getFontFamily
-                (element, ctx, fontFamilyName,
-                 fontWeightString, fontStyleString);
-            if (fontFamily == null) continue;
-            if (fontFamily instanceof UnresolvedFontFamily) {
-                fontFamily = FontFamilyResolver.resolve
-                    ((UnresolvedFontFamily)fontFamily);
-                if (fontFamily == null) continue;
+            fontFamily = SVGFontUtilities.getFontFamily(element, ctx, fontFamilyName,
+                    fontWeightString, fontStyleString);
+            if (fontFamily != null && fontFamily instanceof UnresolvedFontFamily) {
+                fontFamily = ctx.getFontFamilyResolver().resolve(fontFamily.getFamilyName());
+            }
+            if (fontFamily == null) {
+                continue;
             }
             fontFamilyList.add(fontFamily);
-            if (fontFamily instanceof SVGFontFamily) {
-                SVGFontFamily svgFF = (SVGFontFamily)fontFamily;
-                if (svgFF.isComplex()) {
-                    usingComplexSVGFont = true;
-                }
+            if (fontFamily.isComplex()) {
+                usingComplexSVGFont = true;
             }
             GVTFont ft = fontFamily.deriveFont(fontSize, result);
             fontList.add(ft);
diff --git a/sources/org/apache/batik/bridge/UserAgent.java b/sources/org/apache/batik/bridge/UserAgent.java
index 53d9477..8b573e6 100644
--- a/sources/org/apache/batik/bridge/UserAgent.java
+++ b/sources/org/apache/batik/bridge/UserAgent.java
@@ -24,8 +24,10 @@
 import java.awt.geom.Dimension2D;
 
 import org.apache.batik.gvt.event.EventDispatcher;
+import org.apache.batik.gvt.font.FontFamilyResolver;
 import org.apache.batik.gvt.text.Mark;
 import org.apache.batik.util.ParsedURL;
+
 import org.w3c.dom.Element;
 import org.w3c.dom.svg.SVGAElement;
 import org.w3c.dom.svg.SVGDocument;
@@ -306,4 +308,7 @@
      * @param url The url to be loaded as a string.
      */
     void loadDocument(String url);
+
+    /** Returns the Font Family Resolver */
+    public FontFamilyResolver getFontFamilyResolver();
 }
diff --git a/sources/org/apache/batik/bridge/UserAgentAdapter.java b/sources/org/apache/batik/bridge/UserAgentAdapter.java
index fe4925d..0d37567 100644
--- a/sources/org/apache/batik/bridge/UserAgentAdapter.java
+++ b/sources/org/apache/batik/bridge/UserAgentAdapter.java
@@ -28,6 +28,8 @@
 import java.util.Set;
 
 import org.apache.batik.gvt.event.EventDispatcher;
+import org.apache.batik.gvt.font.DefaultFontFamilyResolver;
+import org.apache.batik.gvt.font.FontFamilyResolver;
 import org.apache.batik.gvt.text.Mark;
 import org.apache.batik.util.ParsedURL;
 import org.apache.batik.util.SVGFeatureStrings;
@@ -458,4 +460,11 @@
     public void loadDocument(String url) {
         // Do nothing.
     }
+
+    /**
+     * Returns the Font Family Resolver
+     */
+    public FontFamilyResolver getFontFamilyResolver() {
+        return DefaultFontFamilyResolver.SINGLETON;
+    }
 }
diff --git a/sources/org/apache/batik/gvt/font/AWTFontFamily.java b/sources/org/apache/batik/gvt/font/AWTFontFamily.java
index 1d6dcdc..b51c05a 100644
--- a/sources/org/apache/batik/gvt/font/AWTFontFamily.java
+++ b/sources/org/apache/batik/gvt/font/AWTFontFamily.java
@@ -23,6 +23,7 @@
 import java.text.AttributedCharacterIterator;
 import java.util.HashMap;
 import java.util.Map;
+
 import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
 
 /**
@@ -114,5 +115,9 @@
         fontAttributes.remove(TEXT_COMPOUND_DELIMITER);
         return new AWTGVTFont(fontAttributes);
     }
+
+    public boolean isComplex() {
+        return false;
+    }
      
 }
diff --git a/sources/org/apache/batik/gvt/font/DefaultFontFamilyResolver.java b/sources/org/apache/batik/gvt/font/DefaultFontFamilyResolver.java
new file mode 100644
index 0000000..d77a1e1
--- /dev/null
+++ b/sources/org/apache/batik/gvt/font/DefaultFontFamilyResolver.java
@@ -0,0 +1,187 @@
+/*
+
+   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.batik.gvt.font;
+
+import java.awt.Font;
+import java.awt.GraphicsEnvironment;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * The is a utility class that is used for resolving UnresolvedFontFamilies.
+ *
+ * @author <a href="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
+ * @version $Id$
+ */
+public final class DefaultFontFamilyResolver implements FontFamilyResolver {
+
+    public static final DefaultFontFamilyResolver SINGLETON = new DefaultFontFamilyResolver();
+
+    private DefaultFontFamilyResolver() {
+    }
+
+    /**
+     * The default font. This will be used when no font families can
+     * be resolved for a particular text chunk/run.
+     */
+    private static final AWTFontFamily DEFAULT_FONT_FAMILY =
+            new AWTFontFamily("SansSerif");
+
+    /**
+     * List of all available fonts on the current system, plus a few common
+     * alternatives.
+     */
+    protected static final Map fonts = new HashMap();
+
+    protected static final List awtFontFamilies = new ArrayList();
+
+    protected static final List awtFonts = new ArrayList();
+
+    /**
+     * This sets up the list of available fonts.
+     */
+    static {
+        fonts.put("sans-serif",      "SansSerif");
+        fonts.put("serif",           "Serif");
+        fonts.put("times",           "Serif");
+        fonts.put("times new roman", "Serif");
+        fonts.put("cursive",         "Dialog");
+        fonts.put("fantasy",         "Symbol");
+        fonts.put("monospace",       "Monospaced");
+        fonts.put("monospaced",      "Monospaced");
+        fonts.put("courier",         "Monospaced");
+
+        //
+        // Load all fonts. Work around
+        //
+
+        GraphicsEnvironment env;
+        env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        String[] fontNames = env.getAvailableFontFamilyNames();
+
+        int nFonts = fontNames != null ? fontNames.length : 0;
+        for(int i=0; i<nFonts; i++){
+            fonts.put(fontNames[i].toLowerCase(), fontNames[i]);
+
+            // also add the font name with the spaces removed
+            StringTokenizer st = new StringTokenizer(fontNames[i]);
+            String fontNameWithoutSpaces = "";
+            while (st.hasMoreTokens()) {
+                fontNameWithoutSpaces += st.nextToken();
+            }
+            fonts.put(fontNameWithoutSpaces.toLowerCase(), fontNames[i]);
+
+            // also add the font name with spaces replaced by dashes
+            String fontNameWithDashes = fontNames[i].replace(' ', '-');
+            if (!fontNameWithDashes.equals(fontNames[i])) {
+                fonts.put(fontNameWithDashes.toLowerCase(), fontNames[i]);
+            }
+        }
+
+        //Also register all font names, not just font families.
+        //Example: Font Family: "Univers", but Font Name: "Univers 45 Light"
+        //Without this, matching "Univers 45 Light" is not possible.
+        Font[] allFonts = env.getAllFonts();
+        for (int i = 0; i < allFonts.length; i++) {
+            Font f = allFonts[i];
+            fonts.put(f.getFontName().toLowerCase(), f.getFontName());
+        }
+
+        // first add the default font
+        awtFontFamilies.add(DEFAULT_FONT_FAMILY);
+        awtFonts.add(new AWTGVTFont(DEFAULT_FONT_FAMILY.getFamilyName(), 0, 12));
+
+        Collection fontValues = fonts.values();
+        Iterator iter = fontValues.iterator();
+        while(iter.hasNext()) {
+            String fontFamily = (String)iter.next();
+            AWTFontFamily awtFontFamily = new AWTFontFamily(fontFamily);
+            awtFontFamilies.add(awtFontFamily);
+            AWTGVTFont font = new AWTGVTFont(fontFamily, 0, 12);
+            awtFonts.add(font);
+        }
+
+    }
+
+    /**
+     * This keeps track of all the resolved font families. This is to hopefully
+     * reduce the number of font family objects used.
+     */
+    protected static final Map resolvedFontFamilies = new HashMap();
+
+    /** {@inheritDoc} */
+    public String lookup(String familyName) {
+        return (String)fonts.get(familyName.toLowerCase());
+    }
+
+    /** {@inheritDoc} */
+    public GVTFontFamily resolve(String familyName) {
+
+        familyName = familyName.toLowerCase();
+
+        // first see if this font family has already been resolved
+        GVTFontFamily resolvedFF =
+                (GVTFontFamily)resolvedFontFamilies.get(familyName);
+
+        if (resolvedFF == null) { // hasn't been resolved yet
+            // try to find a matching family name in the list of
+            // available fonts
+            String awtFamilyName = (String)fonts.get(familyName);
+            if (awtFamilyName != null) {
+                resolvedFF = new AWTFontFamily(awtFamilyName);
+            }
+
+            resolvedFontFamilies.put(familyName, resolvedFF);
+        }
+
+        //  if (resolvedFF != null) {
+        //      System.out.println("resolved " + fontFamily.getFamilyName() +
+        //                         " to " + resolvedFF.getFamilyName());
+        //  } else {
+        //      System.out.println("could not resolve " +
+        //                         fontFamily.getFamilyName());
+        //  }
+        return resolvedFF;
+    }
+
+    /** {@inheritDoc} */
+    public GVTFontFamily getFamilyThatCanDisplay(char c) {
+        for (int i = 0; i < awtFontFamilies.size(); i++) {
+            AWTFontFamily fontFamily = (AWTFontFamily)awtFontFamilies.get(i);
+            AWTGVTFont font = (AWTGVTFont)awtFonts.get(i);
+            if (font.canDisplay(c) && fontFamily.getFamilyName().indexOf("Song") == -1) {
+                // the awt font for "MS Song" doesn't display chinese glyphs correctly
+                return fontFamily;
+            }
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public GVTFontFamily getDefault() {
+        return DEFAULT_FONT_FAMILY;
+    }
+
+}
diff --git a/sources/org/apache/batik/gvt/font/FontFamilyResolver.java b/sources/org/apache/batik/gvt/font/FontFamilyResolver.java
index fa98815..d6ff742 100644
--- a/sources/org/apache/batik/gvt/font/FontFamilyResolver.java
+++ b/sources/org/apache/batik/gvt/font/FontFamilyResolver.java
@@ -1,140 +1,27 @@
 /*
-
-   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.
-
+ * 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.batik.gvt.font;
 
-import java.awt.Font;
-import java.awt.GraphicsEnvironment;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.List;
-import java.util.ArrayList;
+public interface FontFamilyResolver {
 
-/**
- * The is a utility class that is used for resolving UnresolvedFontFamilies.
- *
- * @author <a href="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
- * @version $Id$
- */
-public class FontFamilyResolver {
-
-    /**
-     * The default font. This will be used when no font families can
-     * be resolved for a particular text chunk/run.
-     */
-    public static final AWTFontFamily defaultFont =
-        new AWTFontFamily("SansSerif");
-
-    /**
-     * List of all available fonts on the current system, plus a few common
-     * alternatives.
-     */
-    protected static final Map fonts = new HashMap();
-
-    protected static final List awtFontFamilies = new ArrayList();
-    protected static final List awtFonts = new ArrayList();
-
-    /**
-     * This sets up the list of available fonts.
-     */
-    static {
-        fonts.put("sans-serif",      "SansSerif");
-        fonts.put("serif",           "Serif");
-        fonts.put("times",           "Serif");
-        fonts.put("times new roman", "Serif");
-        fonts.put("cursive",         "Dialog");
-        fonts.put("fantasy",         "Symbol");
-        fonts.put("monospace",       "Monospaced");
-        fonts.put("monospaced",      "Monospaced");
-        fonts.put("courier",         "Monospaced");
-
-        //
-        // Load all fonts. Work around
-        //
-
-        GraphicsEnvironment env;
-        env = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        String[] fontNames = env.getAvailableFontFamilyNames();
-
-        int nFonts = fontNames != null ? fontNames.length : 0;
-        for(int i=0; i<nFonts; i++){
-            fonts.put(fontNames[i].toLowerCase(), fontNames[i]);
-
-            // also add the font name with the spaces removed
-            StringTokenizer st = new StringTokenizer(fontNames[i]);
-            String fontNameWithoutSpaces = "";
-            while (st.hasMoreTokens()) {
-                fontNameWithoutSpaces += st.nextToken();
-            }
-            fonts.put(fontNameWithoutSpaces.toLowerCase(), fontNames[i]);
-
-            // also add the font name with spaces replaced by dashes
-            String fontNameWithDashes = fontNames[i].replace(' ', '-');
-            if (!fontNameWithDashes.equals(fontNames[i])) {
-               fonts.put(fontNameWithDashes.toLowerCase(), fontNames[i]);
-            }
-        }
-
-        //Also register all font names, not just font families.
-        //Example: Font Family: "Univers", but Font Name: "Univers 45 Light"
-        //Without this, matching "Univers 45 Light" is not possible.
-        Font[] allFonts = env.getAllFonts();
-        for (int i = 0; i < allFonts.length; i++) {
-            Font f = allFonts[i];
-            fonts.put(f.getFontName().toLowerCase(), f.getFontName());
-        }
-
-        // first add the default font
-        awtFontFamilies.add(defaultFont);
-        awtFonts.add(new AWTGVTFont(defaultFont.getFamilyName(), 0, 12));
-
-        Collection fontValues = fonts.values();
-        Iterator iter = fontValues.iterator();
-        while(iter.hasNext()) {
-            String fontFamily = (String)iter.next();
-            AWTFontFamily awtFontFamily = new AWTFontFamily(fontFamily);
-            awtFontFamilies.add(awtFontFamily);
-            AWTGVTFont font = new AWTGVTFont(fontFamily, 0, 12);
-            awtFonts.add(font);
-        }
-
-    }
-
-    /**
-     * This keeps track of all the resolved font families. This is to hopefully
-     * reduce the number of font family objects used.
-     */
-    protected static final Map resolvedFontFamilies = new HashMap();
-
-    /**
-     * Looks up a font family name and returns the platform name
-     * for the font.
-     *
-     * @param familyName The Font Family name to resolve
-     *
-     * @return The platform name for the font or null if it can't be found.
-     */
-    public static String lookup(String familyName) {
-        return (String)fonts.get(familyName.toLowerCase());
-    }
+    String lookup(String familyName);
 
     /**
      * Resolves a font family name into a GVTFontFamily. If the font
@@ -145,60 +32,11 @@
      * @return A resolved GVTFontFamily or null if the font family could not
      * be resolved.
      */
-    public static GVTFontFamily resolve(String familyName) {
+    GVTFontFamily resolve(String familyName);
 
-        familyName = familyName.toLowerCase();
+    GVTFontFamily getDefault();
 
-        // first see if this font family has already been resolved
-        GVTFontFamily resolvedFF =
-            (GVTFontFamily)resolvedFontFamilies.get(familyName);
+    GVTFontFamily getFamilyThatCanDisplay(char c);
 
-        if (resolvedFF == null) { // hasn't been resolved yet
-            // try to find a matching family name in the list of
-            // available fonts
-            String awtFamilyName = (String)fonts.get(familyName);
-            if (awtFamilyName != null) {
-                resolvedFF = new AWTFontFamily(awtFamilyName);
-            }
-
-            resolvedFontFamilies.put(familyName, resolvedFF);
-        }
-
-        //  if (resolvedFF != null) {
-        //      System.out.println("resolved " + fontFamily.getFamilyName() +
-        //                         " to " + resolvedFF.getFamilyName());
-        //  } else {
-        //      System.out.println("could not resolve " +
-        //                         fontFamily.getFamilyName());
-        //  }
-        return resolvedFF;
-    }
-
-    /**
-     * Resolves an UnresolvedFontFamily into a GVTFontFamily. If the font
-     * family cannot be resolved then null will be returned.
-     *
-     * @param fontFamily The UnresolvedFontFamily to resolve
-     *
-     * @return A resolved GVTFontFamily or null if the font family could not
-     * be resolved.
-     */
-    public static GVTFontFamily resolve(UnresolvedFontFamily fontFamily) {
-
-        return resolve(fontFamily.getFamilyName());
-    }
-
-    public static GVTFontFamily getFamilyThatCanDisplay(char c) {
-        for (int i = 0; i < awtFontFamilies.size(); i++) {
-            AWTFontFamily fontFamily = (AWTFontFamily)awtFontFamilies.get(i);
-            AWTGVTFont font = (AWTGVTFont)awtFonts.get(i);
-            if (font.canDisplay(c) && fontFamily.getFamilyName().indexOf("Song") == -1) {
-                // the awt font for "MS Song" doesn't display chinese glyphs correctly
-                return fontFamily;
-            }
-        }
-
-        return null;
-    }
 
 }
diff --git a/sources/org/apache/batik/gvt/font/GVTFontFamily.java b/sources/org/apache/batik/gvt/font/GVTFontFamily.java
index 4fbcdb2..b379893 100644
--- a/sources/org/apache/batik/gvt/font/GVTFontFamily.java
+++ b/sources/org/apache/batik/gvt/font/GVTFontFamily.java
@@ -19,7 +19,6 @@
 package org.apache.batik.gvt.font;
 
 import java.text.AttributedCharacterIterator;
-
 import java.util.Map;
 
 /**
@@ -57,5 +56,10 @@
      * @param attrs The Attribute Map to get Values from.
      */
     GVTFont deriveFont(float size, Map attrs);
+
+    /**
+     * This method returns true iff the font is a complex SVG font
+     */
+    boolean isComplex();
      
 }
diff --git a/sources/org/apache/batik/gvt/font/UnresolvedFontFamily.java b/sources/org/apache/batik/gvt/font/UnresolvedFontFamily.java
index 1e9633e..dd4362f 100644
--- a/sources/org/apache/batik/gvt/font/UnresolvedFontFamily.java
+++ b/sources/org/apache/batik/gvt/font/UnresolvedFontFamily.java
@@ -85,5 +85,9 @@
      * @param attrs The Attribute Map to get Values from.
      */
     public GVTFont deriveFont(float size, Map attrs) { return null; }
+
+    public boolean isComplex() {
+        return false;
+    }
      
 }
diff --git a/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java b/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
index c3f727b..f6887be 100644
--- a/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
+++ b/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java
@@ -40,6 +40,7 @@
 
 import org.apache.batik.gvt.TextNode;
 import org.apache.batik.gvt.TextPainter;
+import org.apache.batik.gvt.font.DefaultFontFamilyResolver;
 import org.apache.batik.gvt.font.FontFamilyResolver;
 import org.apache.batik.gvt.font.GVTFont;
 import org.apache.batik.gvt.font.GVTFontFamily;
@@ -407,7 +408,7 @@
      *
      * @return The new modified aci.
      */
-    protected static AttributedCharacterIterator createModifiedACIForFontMatching
+    protected AttributedCharacterIterator createModifiedACIForFontMatching
         (AttributedCharacterIterator aci) {
 
         aci.first();
@@ -434,8 +435,7 @@
             // then use the default font
             if (fonts.size() == 0) {
                 // create a list of fonts of the correct size
-                fonts.add(FontFamilyResolver.defaultFont.deriveFont
-                    (fontSize, aci));
+                fonts.add(getFontFamilyResolver().getDefault().deriveFont(fontSize, aci));
             }
 
             // now for each char or group of chars in the string,
@@ -538,7 +538,7 @@
                 } else {
                     char c = aci.setIndex(start+i);
                     GVTFontFamily fontFamily;
-                    fontFamily = FontFamilyResolver.getFamilyThatCanDisplay(c);
+                    fontFamily = getFontFamilyResolver().getFamilyThatCanDisplay(c);
                     // fontFamily = (GVTFontFamily)resolvedFontFamilies.get(0);
 
                     if (runStart == -1) {
@@ -583,6 +583,9 @@
         return aci;
     }
 
+    protected FontFamilyResolver getFontFamilyResolver() {
+        return DefaultFontFamilyResolver.SINGLETON;
+    }
 
     protected TextChunk getTextChunk(TextNode node,
                                      AttributedCharacterIterator aci,
diff --git a/sources/org/apache/batik/swing/svg/JSVGComponent.java b/sources/org/apache/batik/swing/svg/JSVGComponent.java
index ae705d4..7ff841c 100644
--- a/sources/org/apache/batik/swing/svg/JSVGComponent.java
+++ b/sources/org/apache/batik/swing/svg/JSVGComponent.java
@@ -33,6 +33,7 @@
 import java.awt.geom.Dimension2D;
 import java.awt.geom.NoninvertibleTransformException;
 import java.awt.geom.Point2D;
+import java.net.URL;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -40,7 +41,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.net.URL;
 
 import javax.swing.JOptionPane;
 
@@ -68,8 +68,10 @@
 import org.apache.batik.gvt.CompositeGraphicsNode;
 import org.apache.batik.gvt.GraphicsNode;
 import org.apache.batik.gvt.event.EventDispatcher;
-import org.apache.batik.gvt.text.Mark;
+import org.apache.batik.gvt.font.DefaultFontFamilyResolver;
+import org.apache.batik.gvt.font.FontFamilyResolver;
 import org.apache.batik.gvt.renderer.ImageRenderer;
+import org.apache.batik.gvt.text.Mark;
 import org.apache.batik.script.Interpreter;
 import org.apache.batik.swing.gvt.GVTTreeRendererEvent;
 import org.apache.batik.swing.gvt.JGVTComponent;
@@ -80,8 +82,8 @@
 import org.apache.batik.util.SVGFeatureStrings;
 import org.apache.batik.util.XMLResourceDescriptor;
 
-import org.w3c.dom.Document;
 import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.svg.SVGAElement;
 import org.w3c.dom.svg.SVGDocument;
@@ -3095,6 +3097,10 @@
         public void loadDocument(String url) {
             userAgent.loadDocument(url);
         }
+
+        public FontFamilyResolver getFontFamilyResolver() {
+            return userAgent.getFontFamilyResolver();
+        }
     }
 
     /**
@@ -3699,6 +3705,10 @@
         public void loadDocument(String url) {
             JSVGComponent.this.loadSVGDocument(url);
         }
+
+        public FontFamilyResolver getFontFamilyResolver() {
+            return DefaultFontFamilyResolver.SINGLETON;
+        }
     }
 
     protected static final Set FEATURES = new HashSet();