Index: trunk/src/com/kitfox/svg/Font.java
===================================================================
--- trunk/src/com/kitfox/svg/Font.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/Font.java	(revision 8083)
@@ -144,4 +144,9 @@
     }
 
+    public void setFontFace(FontFace face)
+    {
+        fontFace = face;
+    }
+
     public MissingGlyph getGlyph(String unicode)
     {
Index: trunk/src/com/kitfox/svg/FontFace.java
===================================================================
--- trunk/src/com/kitfox/svg/FontFace.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/FontFace.java	(revision 8083)
@@ -54,14 +54,14 @@
      * Em size of coordinate system font is defined in
      */
-    int unitsPerEm = 1000;
-    int ascent = -1;
-    int descent = -1;
-    int accentHeight = -1;
-    int underlinePosition = -1;
-    int underlineThickness = -1;
-    int strikethroughPosition = -1;
-    int strikethroughThickness = -1;
-    int overlinePosition = -1;
-    int overlineThickness = -1;
+    private int unitsPerEm = 1000;
+    private int ascent = -1;
+    private int descent = -1;
+    private int accentHeight = -1;
+    private int underlinePosition = -1;
+    private int underlineThickness = -1;
+    private int strikethroughPosition = -1;
+    private int strikethroughThickness = -1;
+    private int overlinePosition = -1;
+    private int overlineThickness = -1;
 
     /**
@@ -234,3 +234,83 @@
         return false;
     }
+
+    /**
+     * @param unitsPerEm the unitsPerEm to set
+     */
+    public void setUnitsPerEm(int unitsPerEm)
+    {
+        this.unitsPerEm = unitsPerEm;
+    }
+
+    /**
+     * @param ascent the ascent to set
+     */
+    public void setAscent(int ascent)
+    {
+        this.ascent = ascent;
+    }
+
+    /**
+     * @param descent the descent to set
+     */
+    public void setDescent(int descent)
+    {
+        this.descent = descent;
+    }
+
+    /**
+     * @param accentHeight the accentHeight to set
+     */
+    public void setAccentHeight(int accentHeight)
+    {
+        this.accentHeight = accentHeight;
+    }
+
+    /**
+     * @param underlinePosition the underlinePosition to set
+     */
+    public void setUnderlinePosition(int underlinePosition)
+    {
+        this.underlinePosition = underlinePosition;
+    }
+
+    /**
+     * @param underlineThickness the underlineThickness to set
+     */
+    public void setUnderlineThickness(int underlineThickness)
+    {
+        this.underlineThickness = underlineThickness;
+    }
+
+    /**
+     * @param strikethroughPosition the strikethroughPosition to set
+     */
+    public void setStrikethroughPosition(int strikethroughPosition)
+    {
+        this.strikethroughPosition = strikethroughPosition;
+    }
+
+    /**
+     * @param strikethroughThickness the strikethroughThickness to set
+     */
+    public void setStrikethroughThickness(int strikethroughThickness)
+    {
+        this.strikethroughThickness = strikethroughThickness;
+    }
+
+    /**
+     * @param overlinePosition the overlinePosition to set
+     */
+    public void setOverlinePosition(int overlinePosition)
+    {
+        this.overlinePosition = overlinePosition;
+    }
+
+    /**
+     * @param overlineThickness the overlineThickness to set
+     */
+    public void setOverlineThickness(int overlineThickness)
+    {
+        this.overlineThickness = overlineThickness;
+    }
 }
Index: trunk/src/com/kitfox/svg/Group.java
===================================================================
--- trunk/src/com/kitfox/svg/Group.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/Group.java	(revision 8083)
@@ -150,12 +150,14 @@
         //Don't process if not visible
         StyleAttribute styleAttrib = new StyleAttribute();
-        if (getStyle(styleAttrib.setName("visibility")))
-        {
-            if (!styleAttrib.getStringValue().equals("visible"))
+        //Visibility can be overridden by children
+
+        if (getStyle(styleAttrib.setName("display")))
+        {
+            if (styleAttrib.getStringValue().equals("none"))
             {
                 return;
             }
         }
-
+        
         //Do not process offscreen groups
         boolean ignoreClip = diagram.ignoringClipHeuristic();
Index: trunk/src/com/kitfox/svg/Hkern.java
===================================================================
--- trunk/src/com/kitfox/svg/Hkern.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/Hkern.java	(revision 8083)
Index: trunk/src/com/kitfox/svg/ImageSVG.java
===================================================================
--- trunk/src/com/kitfox/svg/ImageSVG.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/ImageSVG.java	(revision 8083)
@@ -207,4 +207,12 @@
         {
             if (!styleAttrib.getStringValue().equals("visible"))
+            {
+                return;
+            }
+        }
+
+        if (getStyle(styleAttrib.setName("display")))
+        {
+            if (styleAttrib.getStringValue().equals("none"))
             {
                 return;
Index: trunk/src/com/kitfox/svg/Marker.java
===================================================================
--- trunk/src/com/kitfox/svg/Marker.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/Marker.java	(revision 8083)
@@ -56,6 +56,6 @@
     float refX;
     float refY;
-    float markerWidth = 3;
-    float markerHeight = 3;
+    float markerWidth = 1;
+    float markerHeight = 1;
     float orient = Float.NaN;
     boolean markerUnitsStrokeWidth = true; //if set to false 'userSpaceOnUse' is assumed
@@ -196,4 +196,6 @@
         boolean changeState = super.updateTime(curTime);
 
+        build();
+        
         //Marker properties do not change
         return changeState;
Index: trunk/src/com/kitfox/svg/MissingGlyph.java
===================================================================
--- trunk/src/com/kitfox/svg/MissingGlyph.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/MissingGlyph.java	(revision 8083)
@@ -59,10 +59,10 @@
     
     //We may define a path
-    Shape path = null;
+    private Shape path = null;
     //Alternately, we may have child graphical elements
-    int horizAdvX = -1;  //Inherits font's value if not set
-    int vertOriginX = -1;  //Inherits font's value if not set
-    int vertOriginY = -1;  //Inherits font's value if not set
-    int vertAdvY = -1;  //Inherits font's value if not set
+    private int horizAdvX = -1;  //Inherits font's value if not set
+    private int vertOriginX = -1;  //Inherits font's value if not set
+    private int vertOriginY = -1;  //Inherits font's value if not set
+    private int vertAdvY = -1;  //Inherits font's value if not set
 
     /**
@@ -242,3 +242,43 @@
         return false;
     }
+
+    /**
+     * @param path the path to set
+     */
+    public void setPath(Shape path)
+    {
+        this.path = path;
+    }
+
+    /**
+     * @param horizAdvX the horizAdvX to set
+     */
+    public void setHorizAdvX(int horizAdvX)
+    {
+        this.horizAdvX = horizAdvX;
+    }
+
+    /**
+     * @param vertOriginX the vertOriginX to set
+     */
+    public void setVertOriginX(int vertOriginX)
+    {
+        this.vertOriginX = vertOriginX;
+    }
+
+    /**
+     * @param vertOriginY the vertOriginY to set
+     */
+    public void setVertOriginY(int vertOriginY)
+    {
+        this.vertOriginY = vertOriginY;
+    }
+
+    /**
+     * @param vertAdvY the vertAdvY to set
+     */
+    public void setVertAdvY(int vertAdvY)
+    {
+        this.vertAdvY = vertAdvY;
+    }
 }
Index: trunk/src/com/kitfox/svg/SVGDisplayPanel.java
===================================================================
--- trunk/src/com/kitfox/svg/SVGDisplayPanel.java	(revision 8081)
+++ 	(revision )
@@ -1,207 +1,0 @@
-/*
- * SVG Salamander
- * Copyright (c) 2004, Mark McKay
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or 
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- *   - Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the following
- *     disclaimer.
- *   - Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials 
- *     provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE. 
- * 
- * Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
- * projects can be found at http://www.kitfox.com
- *
- * Created on February 20, 2004, 12:29 PM
- */
-
-package com.kitfox.svg;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.geom.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * @author Mark McKay
- * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
- */
-public class SVGDisplayPanel extends javax.swing.JPanel implements Scrollable
-{
-    public static final long serialVersionUID = 1;
-    
-    SVGDiagram diagram = null;
-    float scale = 1f;
-    Color bgColor = null;
-
-    /** Creates new form SVGDisplayPanel */
-    public SVGDisplayPanel()
-    {
-        initComponents();
-    }
-
-    public SVGDiagram getDiagram()
-    {
-        return diagram;
-    }
-    
-    public void setDiagram(SVGDiagram diagram)
-    {
-        this.diagram = diagram;
-        diagram.setDeviceViewport(getBounds());
-        
-        setDimension();
-    }
-
-    public void setScale(float scale)
-    {
-        this.scale = scale;
-        setDimension();
-    }
-
-    public void setBgColor(Color col)
-    {
-        bgColor = col;
-    }
-
-    private void setDimension()
-    {
-        if (diagram == null)
-        {
-            setPreferredSize(new Dimension(1, 1));
-            revalidate();
-            return;
-        }
-
-        final Rectangle2D.Float rect = new Rectangle2D.Float();
-        diagram.getViewRect(rect);
-
-        int w = (int)(rect.width * scale);
-        int h = (int)(rect.height * scale);
-
-        setPreferredSize(new Dimension(w, h));
-        revalidate();
-    }
-
-    /**
-     * Update this image to reflect the passed time
-     */
-    public void updateTime(double curTime) throws SVGException
-    {
-        if (diagram == null) return;
-        
-        diagram.updateTime(curTime);
-    }
-    
-    public void paintComponent(Graphics gg)
-    {
-        Graphics2D g = (Graphics2D)gg;
-
-        if (bgColor != null)
-        {
-            Dimension dim = getSize();
-            g.setColor(bgColor);
-            g.fillRect(0, 0, dim.width, dim.height);
-        }
-
-        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
-        if (diagram != null) 
-        {
-            try
-            {
-                diagram.render(g);
-            }
-            catch (SVGException e)
-            {
-                Logger.getLogger(SVGConst.SVG_LOGGER).log(Level.WARNING, 
-                    "Could not render diagram", e);
-            }
-        }
-    }
-
-    /** This method is called from within the constructor to
-     * initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is
-     * always regenerated by the Form Editor.
-     */
-    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
-    private void initComponents()
-    {
-
-        setLayout(new java.awt.BorderLayout());
-
-        addComponentListener(new java.awt.event.ComponentAdapter()
-        {
-            public void componentResized(java.awt.event.ComponentEvent evt)
-            {
-                formComponentResized(evt);
-            }
-        });
-
-    }// </editor-fold>//GEN-END:initComponents
-
-    private void formComponentResized(java.awt.event.ComponentEvent evt)//GEN-FIRST:event_formComponentResized
-    {//GEN-HEADEREND:event_formComponentResized
-        if (diagram != null)
-        {
-            diagram.setDeviceViewport(getBounds());
-            setDimension();
-        }
-
-    }//GEN-LAST:event_formComponentResized
-
-    public Dimension getPreferredScrollableViewportSize()
-    {
-        return getPreferredSize();
-    }
-
-    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
-    {
-        if (orientation == SwingConstants.HORIZONTAL)
-        {
-            return visibleRect.width;
-        }
-        else return visibleRect.height;
-    }
-
-    public boolean getScrollableTracksViewportHeight()
-    {
-        return false;
-    }
-
-    public boolean getScrollableTracksViewportWidth()
-    {
-        return false;
-    }
-
-    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
-    {
-        return getScrollableBlockIncrement(visibleRect, orientation, direction) / 16;
-    }
-
-
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    // End of variables declaration//GEN-END:variables
-
-}
Index: trunk/src/com/kitfox/svg/SVGElement.java
===================================================================
--- trunk/src/com/kitfox/svg/SVGElement.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/SVGElement.java	(revision 8083)
@@ -588,5 +588,5 @@
     static public AffineTransform parseSingleTransform(String val) throws SVGException
     {
-        final Matcher matchWord = Pattern.compile("([a-zA-Z]+|-?\\d+(\\.\\d+)?|-?\\.\\d+)").matcher("");
+        final Matcher matchWord = Pattern.compile("([a-zA-Z]+|-?\\d+(\\.\\d+)?(e-?\\d+)?|-?\\.\\d+(e-?\\d+)?)").matcher("");
 
         AffineTransform retXform = new AffineTransform();
Index: trunk/src/com/kitfox/svg/Text.java
===================================================================
--- trunk/src/com/kitfox/svg/Text.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/Text.java	(revision 8083)
@@ -36,4 +36,6 @@
 package com.kitfox.svg;
 
+import com.kitfox.svg.util.FontSystem;
+import com.kitfox.svg.util.TextBuilder;
 import com.kitfox.svg.xml.StyleAttribute;
 import java.awt.Graphics2D;
@@ -89,4 +91,7 @@
     int fontWeight;
 
+    float textLength = -1;
+    String lengthAdjust = "spacing";
+    
     /**
      * Creates a new instance of Stop
@@ -167,5 +172,6 @@
         {
             fontFamily = sty.getStringValue();
-        } else
+        }
+        else
         {
             fontFamily = "Sans Serif";
@@ -175,7 +181,26 @@
         {
             fontSize = sty.getFloatValueWithUnits();
-        } else
+        }
+        else
         {
             fontSize = 12f;
+        }
+
+        if (getStyle(sty.setName("textLength")))
+        {
+            textLength = sty.getFloatValueWithUnits();
+        }
+        else
+        {
+            textLength = -1;
+        }
+
+        if (getStyle(sty.setName("lengthAdjust")))
+        {
+            lengthAdjust = sty.getStringValue();
+        }
+        else
+        {
+            lengthAdjust = "spacing";
         }
 
@@ -235,31 +260,9 @@
         //text-rendering
 
-        buildFont();
-    }
-
-    protected void buildFont() throws SVGException
-    {
-        int style;
-        switch (fontStyle)
-        {
-            case TXST_ITALIC:
-                style = java.awt.Font.ITALIC;
-                break;
-            default:
-                style = java.awt.Font.PLAIN;
-                break;
-        }
-
-        int weight;
-        switch (fontWeight)
-        {
-            case TXWE_BOLD:
-            case TXWE_BOLDER:
-                weight = java.awt.Font.BOLD;
-                break;
-            default:
-                weight = java.awt.Font.PLAIN;
-                break;
-        }
+        buildText();
+    }
+
+    protected void buildText() throws SVGException
+    {
 
         //Get font
@@ -269,7 +272,8 @@
 //            System.err.println("Could not load font");
 
-            java.awt.Font sysFont = new java.awt.Font(fontFamily, style | weight, (int) fontSize);
-            buildSysFont(sysFont);
-            return;
+            font = new FontSystem(fontFamily, fontStyle, fontWeight, (int)fontSize);
+//            java.awt.Font sysFont = new java.awt.Font(fontFamily, style | weight, (int)fontSize);
+//            buildSysFont(sysFont);
+//            return;
         }
 
@@ -288,4 +292,42 @@
 
 //        AffineTransform oldXform = g.getTransform();
+//        TextBuilder builder = new TextBuilder();
+//        
+//        for (Iterator it = content.iterator(); it.hasNext();)
+//        {
+//            Object obj = it.next();
+//
+//            if (obj instanceof String)
+//            {
+//                String text = (String) obj;
+//                if (text != null)
+//                {
+//                    text = text.trim();
+//                }
+//                
+//                for (int i = 0; i < text.length(); i++)
+//                {
+//                    String unicode = text.substring(i, i + 1);
+//                    MissingGlyph glyph = font.getGlyph(unicode);
+//                    
+//                    builder.appendGlyph(glyph);
+//                }
+//            }
+//            else if (obj instanceof Tspan)
+//            {
+//                Tspan tspan = (Tspan)obj;
+//                tspan.buildGlyphs(builder);
+//            }
+//        }
+//
+//        builder.formatGlyphs();
+        
+        
+
+                
+                
+        
+        
+        
         AffineTransform xform = new AffineTransform();
 
@@ -328,93 +370,23 @@
 
                 strokeWidthScalar = 1f;
-            } else if (obj instanceof Tspan)
-            {
-                Tspan tspan = (Tspan) obj;
-
-                xform.setToIdentity();
-                xform.setToTranslation(cursorX, cursorY);
-                xform.scale(fontScale, fontScale);
-//                tspan.setCursorX(cursorX);
-//                tspan.setCursorY(cursorY);
-
-                Shape tspanShape = tspan.getShape();
-                tspanShape = xform.createTransformedShape(tspanShape);
-                textPath.append(tspanShape, false);
-//                tspan.render(g);
-//                cursorX = tspan.getCursorX();
-//                cursorY = tspan.getCursorY();
-            }
-
-        }
-
-        switch (textAnchor)
-        {
-            case TXAN_MIDDLE:
-            {
-                AffineTransform at = new AffineTransform();
-                at.translate(-textPath.getBounds().getWidth() / 2, 0);
-                textPath.transform(at);
-                break;
-            }
-            case TXAN_END:
-            {
-                AffineTransform at = new AffineTransform();
-                at.translate(-textPath.getBounds().getWidth(), 0);
-                textPath.transform(at);
-                break;
-            }
-        }
-    }
-
-    private void buildSysFont(java.awt.Font font) throws SVGException
-    {
-        GeneralPath textPath = new GeneralPath();
-        textShape = textPath;
-
-        float cursorX = x, cursorY = y;
-
-//        FontMetrics fm = g.getFontMetrics(font);
-        FontRenderContext frc = new FontRenderContext(null, true, true);
-
-//        FontFace fontFace = font.getFontFace();
-        //int unitsPerEm = fontFace.getUnitsPerEm();
-//        int ascent = fm.getAscent();
-//        float fontScale = fontSize / (float)ascent;
-
-//        AffineTransform oldXform = g.getTransform();
-        AffineTransform xform = new AffineTransform();
-
-        for (Iterator it = content.iterator(); it.hasNext();)
-        {
-            Object obj = it.next();
-
-            if (obj instanceof String)
-            {
-                String text = (String)obj;
-                text = text.trim();
-
-                Shape textShape = font.createGlyphVector(frc, text).getOutline(cursorX, cursorY);
-                textPath.append(textShape, false);
-//                renderShape(g, textShape);
-//                g.drawString(text, cursorX, cursorY);
-
-                Rectangle2D rect = font.getStringBounds(text, frc);
-                cursorX += (float) rect.getWidth();
-            } else if (obj instanceof Tspan)
-            {
-                /*
-                 Tspan tspan = (Tspan)obj;
-                 
-                 xform.setToIdentity();
-                 xform.setToTranslation(cursorX, cursorY);
-                 
-                 Shape tspanShape = tspan.getShape();
-                 tspanShape = xform.createTransformedShape(tspanShape);
-                 textArea.add(new Area(tspanShape));
-                 
-                 cursorX += tspanShape.getBounds2D().getWidth();
-                 */
-
-
+            }
+            else if (obj instanceof Tspan)
+            {
+//                Tspan tspan = (Tspan) obj;
+//
+//                xform.setToIdentity();
+//                xform.setToTranslation(cursorX, cursorY);
+//                xform.scale(fontScale, fontScale);
+////                tspan.setCursorX(cursorX);
+////                tspan.setCursorY(cursorY);
+//
+//                Shape tspanShape = tspan.getShape();
+//                tspanShape = xform.createTransformedShape(tspanShape);
+//                textPath.append(tspanShape, false);
+////                tspan.render(g);
+////                cursorX = tspan.getCursorX();
+////                cursorY = tspan.getCursorY();
+                
+                
                 Tspan tspan = (Tspan)obj;
                 Point2D cursor = new Point2D.Float(cursorX, cursorY);
@@ -426,6 +398,7 @@
                 cursorX = (float)cursor.getX();
                 cursorY = (float)cursor.getY();
-
-            }
+                
+            }
+
         }
 
@@ -442,5 +415,5 @@
             {
                 AffineTransform at = new AffineTransform();
-                at.translate(-Math.ceil(textPath.getBounds().getWidth()), 0);
+                at.translate(-textPath.getBounds().getWidth(), 0);
                 textPath.transform(at);
                 break;
@@ -448,4 +421,86 @@
         }
     }
+
+//    private void buildSysFont(java.awt.Font font) throws SVGException
+//    {
+//        GeneralPath textPath = new GeneralPath();
+//        textShape = textPath;
+//
+//        float cursorX = x, cursorY = y;
+//
+////        FontMetrics fm = g.getFontMetrics(font);
+//        FontRenderContext frc = new FontRenderContext(null, true, true);
+//
+////        FontFace fontFace = font.getFontFace();
+//        //int unitsPerEm = fontFace.getUnitsPerEm();
+////        int ascent = fm.getAscent();
+////        float fontScale = fontSize / (float)ascent;
+//
+////        AffineTransform oldXform = g.getTransform();
+//        AffineTransform xform = new AffineTransform();
+//
+//        for (Iterator it = content.iterator(); it.hasNext();)
+//        {
+//            Object obj = it.next();
+//
+//            if (obj instanceof String)
+//            {
+//                String text = (String)obj;
+//                text = text.trim();
+//
+//                Shape textShape = font.createGlyphVector(frc, text).getOutline(cursorX, cursorY);
+//                textPath.append(textShape, false);
+////                renderShape(g, textShape);
+////                g.drawString(text, cursorX, cursorY);
+//
+//                Rectangle2D rect = font.getStringBounds(text, frc);
+//                cursorX += (float) rect.getWidth();
+//            } else if (obj instanceof Tspan)
+//            {
+//                /*
+//                 Tspan tspan = (Tspan)obj;
+//                 
+//                 xform.setToIdentity();
+//                 xform.setToTranslation(cursorX, cursorY);
+//                 
+//                 Shape tspanShape = tspan.getShape();
+//                 tspanShape = xform.createTransformedShape(tspanShape);
+//                 textArea.add(new Area(tspanShape));
+//                 
+//                 cursorX += tspanShape.getBounds2D().getWidth();
+//                 */
+//
+//
+//                Tspan tspan = (Tspan)obj;
+//                Point2D cursor = new Point2D.Float(cursorX, cursorY);
+////                tspan.setCursorX(cursorX);
+////                tspan.setCursorY(cursorY);
+//                tspan.appendToShape(textPath, cursor);
+////                cursorX = tspan.getCursorX();
+////                cursorY = tspan.getCursorY();
+//                cursorX = (float)cursor.getX();
+//                cursorY = (float)cursor.getY();
+//
+//            }
+//        }
+//
+//        switch (textAnchor)
+//        {
+//            case TXAN_MIDDLE:
+//            {
+//                AffineTransform at = new AffineTransform();
+//                at.translate(-textPath.getBounds().getWidth() / 2, 0);
+//                textPath.transform(at);
+//                break;
+//            }
+//            case TXAN_END:
+//            {
+//                AffineTransform at = new AffineTransform();
+//                at.translate(-Math.ceil(textPath.getBounds().getWidth()), 0);
+//                textPath.transform(at);
+//                break;
+//            }
+//        }
+//    }
 
     public void render(Graphics2D g) throws SVGException
@@ -502,4 +557,22 @@
         }
 
+        if (getStyle(sty.setName("textLength")))
+        {
+            textLength = sty.getFloatValueWithUnits();
+        }
+        else
+        {
+            textLength = -1;
+        }
+
+        if (getStyle(sty.setName("lengthAdjust")))
+        {
+            lengthAdjust = sty.getStringValue();
+        }
+        else
+        {
+            lengthAdjust = "spacing";
+        }
+
         if (getPres(sty.setName("font-family")))
         {
Index: trunk/src/com/kitfox/svg/Tspan.java
===================================================================
--- trunk/src/com/kitfox/svg/Tspan.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/Tspan.java	(revision 8083)
@@ -36,4 +36,5 @@
 package com.kitfox.svg;
 
+import com.kitfox.svg.util.FontSystem;
 import com.kitfox.svg.xml.StyleAttribute;
 import java.awt.Graphics2D;
@@ -168,20 +169,4 @@
     public void appendToShape(GeneralPath addShape, Point2D cursor) throws SVGException
     {
-//        if (x != null)
-//        {
-//            cursorX = x[0];
-//        } else if (dx != null)
-//        {
-//            cursorX += dx[0];
-//        }
-//
-//        if (y != null)
-//        {
-//            cursorY = y[0];
-//        } else if (dy != null)
-//        {
-//            cursorY += dy[0];
-//        }
-
         StyleAttribute sty = new StyleAttribute();
 
@@ -203,4 +188,39 @@
         {
             letterSpacing = sty.getFloatValueWithUnits();
+        }
+
+        int fontStyle = 0;
+        if (getStyle(sty.setName("font-style")))
+        {
+            String s = sty.getStringValue();
+            if ("normal".equals(s))
+            {
+                fontStyle = Text.TXST_NORMAL;
+            } else if ("italic".equals(s))
+            {
+                fontStyle = Text.TXST_ITALIC;
+            } else if ("oblique".equals(s))
+            {
+                fontStyle = Text.TXST_OBLIQUE;
+            }
+        } else
+        {
+            fontStyle = Text.TXST_NORMAL;
+        }
+
+        int fontWeight = 0;
+        if (getStyle(sty.setName("font-weight")))
+        {
+            String s = sty.getStringValue();
+            if ("normal".equals(s))
+            {
+                fontWeight = Text.TXWE_NORMAL;
+            } else if ("bold".equals(s))
+            {
+                fontWeight = Text.TXWE_BOLD;
+            }
+        } else
+        {
+            fontWeight = Text.TXWE_NORMAL;
         }
 
@@ -210,6 +230,7 @@
         if (font == null)
         {
-            addShapeSysFont(addShape, font, fontFamily, fontSize, letterSpacing, cursor);
-            return;
+            font = new FontSystem(fontFamily, fontStyle, fontWeight, (int)fontSize);
+//            addShapeSysFont(addShape, font, fontFamily, fontSize, letterSpacing, cursor);
+//            return;
         }
 
@@ -275,59 +296,59 @@
     }
 
-    private void addShapeSysFont(GeneralPath addShape, Font font,
-        String fontFamily, float fontSize, float letterSpacing, Point2D cursor)
-    {
-
-        java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int) fontSize);
-
-        FontRenderContext frc = new FontRenderContext(null, true, true);
-        String renderText = this.text.trim();
-
-        AffineTransform xform = new AffineTransform();
-
-        float cursorX = (float)cursor.getX();
-        float cursorY = (float)cursor.getY();
-//        int i = 0;
-        for (int i = 0; i < renderText.length(); i++)
-        {
-            if (x != null && i < x.length)
-            {
-                cursorX = x[i];
-            } else if (dx != null && i < dx.length)
-            {
-                cursorX += dx[i];
-            }
-
-            if (y != null && i < y.length)
-            {
-                cursorY = y[i];
-            } else if (dy != null && i < dy.length)
-            {
-                cursorY += dy[i];
-            }
-//            i++;
-            
-            xform.setToIdentity();
-            xform.setToTranslation(cursorX, cursorY);
-            if (rotate != null)
-            {
-                xform.rotate(rotate[Math.min(i, rotate.length - 1)]);
-            }
-
-//            String unicode = renderText.substring(i, i + 1);
-            GlyphVector textVector = sysFont.createGlyphVector(frc, renderText.substring(i, i + 1));
-            Shape glyphOutline = textVector.getGlyphOutline(0);
-            GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(0);
-
-            glyphOutline = xform.createTransformedShape(glyphOutline);
-            addShape.append(glyphOutline, false);
-
-
-//            cursorX += fontScale * glyph.getHorizAdvX() + letterSpacing;
-            cursorX += glyphMetrics.getAdvance() + letterSpacing;
-        }
-        
-        cursor.setLocation(cursorX, cursorY);
-    }
+//    private void addShapeSysFont(GeneralPath addShape, Font font,
+//        String fontFamily, float fontSize, float letterSpacing, Point2D cursor)
+//    {
+//
+//        java.awt.Font sysFont = new java.awt.Font(fontFamily, java.awt.Font.PLAIN, (int) fontSize);
+//
+//        FontRenderContext frc = new FontRenderContext(null, true, true);
+//        String renderText = this.text.trim();
+//
+//        AffineTransform xform = new AffineTransform();
+//
+//        float cursorX = (float)cursor.getX();
+//        float cursorY = (float)cursor.getY();
+////        int i = 0;
+//        for (int i = 0; i < renderText.length(); i++)
+//        {
+//            if (x != null && i < x.length)
+//            {
+//                cursorX = x[i];
+//            } else if (dx != null && i < dx.length)
+//            {
+//                cursorX += dx[i];
+//            }
+//
+//            if (y != null && i < y.length)
+//            {
+//                cursorY = y[i];
+//            } else if (dy != null && i < dy.length)
+//            {
+//                cursorY += dy[i];
+//            }
+////            i++;
+//            
+//            xform.setToIdentity();
+//            xform.setToTranslation(cursorX, cursorY);
+//            if (rotate != null)
+//            {
+//                xform.rotate(rotate[Math.min(i, rotate.length - 1)]);
+//            }
+//
+////            String unicode = renderText.substring(i, i + 1);
+//            GlyphVector textVector = sysFont.createGlyphVector(frc, renderText.substring(i, i + 1));
+//            Shape glyphOutline = textVector.getGlyphOutline(0);
+//            GlyphMetrics glyphMetrics = textVector.getGlyphMetrics(0);
+//
+//            glyphOutline = xform.createTransformedShape(glyphOutline);
+//            addShape.append(glyphOutline, false);
+//
+//
+////            cursorX += fontScale * glyph.getHorizAdvX() + letterSpacing;
+//            cursorX += glyphMetrics.getAdvance() + letterSpacing;
+//        }
+//        
+//        cursor.setLocation(cursorX, cursorY);
+//    }
 
     public void render(Graphics2D g) throws SVGException
Index: trunk/src/com/kitfox/svg/app/data/Handler.java
===================================================================
--- trunk/src/com/kitfox/svg/app/data/Handler.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/app/data/Handler.java	(revision 8083)
Index: trunk/src/com/kitfox/svg/util/FontSystem.java
===================================================================
--- trunk/src/com/kitfox/svg/util/FontSystem.java	(revision 8083)
+++ trunk/src/com/kitfox/svg/util/FontSystem.java	(revision 8083)
@@ -0,0 +1,90 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.kitfox.svg.util;
+
+import com.kitfox.svg.Font;
+import com.kitfox.svg.FontFace;
+import com.kitfox.svg.Glyph;
+import com.kitfox.svg.MissingGlyph;
+import java.awt.Canvas;
+import java.awt.FontMetrics;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphMetrics;
+import java.awt.font.GlyphVector;
+import java.util.HashMap;
+
+/**
+ *
+ * @author kitfox
+ */
+public class FontSystem extends Font
+{
+    java.awt.Font sysFont;
+    FontMetrics fm;
+
+    HashMap glyphCache = new HashMap();
+    
+    public FontSystem(String fontFamily, int fontStyle, int fontWeight, int fontSize)
+    {
+        int style;
+        switch (fontStyle)
+        {
+            case com.kitfox.svg.Text.TXST_ITALIC:
+                style = java.awt.Font.ITALIC;
+                break;
+            default:
+                style = java.awt.Font.PLAIN;
+                break;
+        }
+
+        int weight;
+        switch (fontWeight)
+        {
+            case com.kitfox.svg.Text.TXWE_BOLD:
+            case com.kitfox.svg.Text.TXWE_BOLDER:
+                weight = java.awt.Font.BOLD;
+                break;
+            default:
+                weight = java.awt.Font.PLAIN;
+                break;
+        }
+        sysFont = new java.awt.Font(fontFamily, style | weight, (int) fontSize);
+        
+        Canvas c = new Canvas();
+        fm = c.getFontMetrics(sysFont);
+        
+        FontFace face = new FontFace();
+        face.setAscent(fm.getAscent());
+        face.setDescent(fm.getDescent());
+        face.setUnitsPerEm(fm.charWidth('M'));
+        setFontFace(face);
+    }
+
+    public MissingGlyph getGlyph(String unicode)
+    {
+        FontRenderContext frc = new FontRenderContext(null, true, true);
+        GlyphVector vec = sysFont.createGlyphVector(frc, unicode);
+        
+        Glyph glyph = (Glyph)glyphCache.get(unicode);
+        if (glyph == null)
+        {
+            glyph = new Glyph();
+            glyph.setPath(vec.getGlyphOutline(0));
+
+            GlyphMetrics gm = vec.getGlyphMetrics(0);
+            glyph.setHorizAdvX((int)gm.getAdvanceX());
+            glyph.setVertAdvY((int)gm.getAdvanceY());
+            glyph.setVertOriginX(0);
+            glyph.setVertOriginY(0);
+            
+            glyphCache.put(unicode, glyph);
+        }
+        
+        return glyph;
+    }
+    
+    
+}
Index: trunk/src/com/kitfox/svg/util/TextBuilder.java
===================================================================
--- trunk/src/com/kitfox/svg/util/TextBuilder.java	(revision 8083)
+++ trunk/src/com/kitfox/svg/util/TextBuilder.java	(revision 8083)
@@ -0,0 +1,15 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.kitfox.svg.util;
+
+/**
+ *
+ * @author kitfox
+ */
+public class TextBuilder
+{
+    
+}
Index: trunk/src/com/kitfox/svg/xml/Base64InputStream.java
===================================================================
--- trunk/src/com/kitfox/svg/xml/Base64InputStream.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/xml/Base64InputStream.java	(revision 8083)
Index: trunk/src/com/kitfox/svg/xml/Base64OutputStream.java
===================================================================
--- trunk/src/com/kitfox/svg/xml/Base64OutputStream.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/xml/Base64OutputStream.java	(revision 8083)
Index: trunk/src/com/kitfox/svg/xml/Base64Util.java
===================================================================
--- trunk/src/com/kitfox/svg/xml/Base64Util.java	(revision 8081)
+++ trunk/src/com/kitfox/svg/xml/Base64Util.java	(revision 8083)
