You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by de...@apache.org on 2005/09/25 21:53:33 UTC

svn commit: r291468 [1/19] - in /xmlgraphics/batik/trunk: ./ samples/tests/resources/wmf/ sources/org/apache/batik/ext/awt/geom/ sources/org/apache/batik/svggen/ sources/org/apache/batik/transcoder/ sources/org/apache/batik/transcoder/wmf/ sources/org/...

Author: deweese
Date: Sun Sep 25 12:51:54 2005
New Revision: 291468

URL: http://svn.apache.org/viewcvs?rev=291468&view=rev
Log:
Patch for improved WMF & Graphics2D from Herve Girod (PR 36309).
Thanks Herve!
1) XMLWriter now tries to avoid inserting whitespace (it's added
   inside tags before the close '>').  This means that the
   DOM generated will be different.  This avoids messing up generated
   tspans.
2) WMF Transparency doesn't seem to be carried through (testCard.wmf)
3) WMF Bitmap fill doesn't seem to align quite right (testCard.wmf)
4) Polygon2D & PolyLine2D should probably share a common base class.
5) SVGGraphics2D - attributed character iterator stuff is a bit
   different (handles more cases, more correctly I think).  Also
   drops back to stroking in a fairly configurable manner.
6) New regard test to turn WMF into SVG and compair with reference.

Added:
    xmlgraphics/batik/trunk/samples/tests/resources/wmf/
      - copied from r291451, xmlgraphics/batik/branches/svg11/samples/tests/resources/wmf/
    xmlgraphics/batik/trunk/samples/tests/resources/wmf/black_shapes.wmf
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/samples/tests/resources/wmf/black_shapes.wmf
    xmlgraphics/batik/trunk/samples/tests/resources/wmf/imageWMF.wmf
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/samples/tests/resources/wmf/imageWMF.wmf
    xmlgraphics/batik/trunk/samples/tests/resources/wmf/testChart.wmf
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/samples/tests/resources/wmf/testChart.wmf
    xmlgraphics/batik/trunk/samples/tests/resources/wmf/textGreek.wmf
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/samples/tests/resources/wmf/textGreek.wmf
    xmlgraphics/batik/trunk/sources/org/apache/batik/ext/awt/geom/Polygon2D.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/geom/Polygon2D.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/ext/awt/geom/Polyline2D.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/geom/Polyline2D.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/ToSVGAbstractTranscoder.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/ToSVGAbstractTranscoder.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/AbstractWMFPainter.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/AbstractWMFPainter.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/AbstractWMFReader.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/AbstractWMFReader.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/GdiObject.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/GdiObject.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/MetaRecord.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/MetaRecord.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/TextureFactory.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/TextureFactory.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/WMFFont.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/WMFFont.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/WMFHeaderProperties.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/WMFHeaderProperties.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/package.html
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/package.html
    xmlgraphics/batik/trunk/test-references/org/apache/batik/transcoder/wmf/   (props changed)
      - copied from r291451, xmlgraphics/batik/branches/svg11/test-references/org/apache/batik/transcoder/wmf/
    xmlgraphics/batik/trunk/test-references/org/apache/batik/transcoder/wmf/black_shapes.svg
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/test-references/org/apache/batik/transcoder/wmf/black_shapes.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/transcoder/wmf/imageWMF.svg
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/test-references/org/apache/batik/transcoder/wmf/imageWMF.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/transcoder/wmf/testChart.svg
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/test-references/org/apache/batik/transcoder/wmf/testChart.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/transcoder/wmf/textGreek.svg
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/test-references/org/apache/batik/transcoder/wmf/textGreek.svg
    xmlgraphics/batik/trunk/test-resources/org/apache/batik/transcoder/wmf/
      - copied from r291451, xmlgraphics/batik/branches/svg11/test-resources/org/apache/batik/transcoder/wmf/
    xmlgraphics/batik/trunk/test-resources/org/apache/batik/transcoder/wmf/resources/
      - copied from r291451, xmlgraphics/batik/branches/svg11/test-resources/org/apache/batik/transcoder/wmf/resources/
    xmlgraphics/batik/trunk/test-resources/org/apache/batik/transcoder/wmf/resources/Messages.properties
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/test-resources/org/apache/batik/transcoder/wmf/resources/Messages.properties
    xmlgraphics/batik/trunk/test-sources/org/apache/batik/transcoder/wmf/
      - copied from r291451, xmlgraphics/batik/branches/svg11/test-sources/org/apache/batik/transcoder/wmf/
    xmlgraphics/batik/trunk/test-sources/org/apache/batik/transcoder/wmf/Messages.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/test-sources/org/apache/batik/transcoder/wmf/Messages.java
    xmlgraphics/batik/trunk/test-sources/org/apache/batik/transcoder/wmf/WMFAccuracyTest.java
      - copied unchanged from r291451, xmlgraphics/batik/branches/svg11/test-sources/org/apache/batik/transcoder/wmf/WMFAccuracyTest.java
Modified:
    xmlgraphics/batik/trunk/build.xml
    xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/DOMGroupManager.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGFont.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGGraphics2D.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/XmlWriter.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/WMFConstants.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/RecordStore.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/WMFPainter.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/WMFRecordStore.java
    xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/WMFTranscoder.java
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ATransform.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/AttributedCharacterIterator.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/BStroke.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/BasicShapes.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/BasicShapes2.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Bug17965.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Bug4389.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Bug4945.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Bug6535.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Clip.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Color1.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Color2.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextATransform.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextAttributedCharacterIterator.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextBStroke.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextBasicShapes.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextBasicShapes2.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextBug17965.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextBug4389.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextBug4945.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextBug6535.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextClip.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextColor1.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextColor2.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextDrawImage.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextFont1.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextFont2.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextGVector.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextGradient.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextGraphicObjects.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextIdentityTest.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextLookup.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextNegativeLengths.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextPaints.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextRHints.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextRescale.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextShearTest.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextTextSpacePreserve.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextTexture.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ContextTransformCollapse.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/DrawImage.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Font1.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Font2.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/GVector.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Gradient.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/GraphicObjects.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/IdentityTest.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Lookup.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/NegativeLengths.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Paints.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/RHints.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Rescale.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/ShearTest.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/TextSpacePreserve.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/Texture.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/TransformCollapse.svg
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/rendering/AttributedCharacterIterator.png
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/rendering/ContextAttributedCharacterIterator.png
    xmlgraphics/batik/trunk/test-references/org/apache/batik/svggen/rendering/ContextBug4945.png
    xmlgraphics/batik/trunk/test-resources/org/apache/batik/transcoder/unitTesting.xml
    xmlgraphics/batik/trunk/test-sources/org/apache/batik/svggen/AttributedCharacterIterator.java
    xmlgraphics/batik/trunk/test-sources/org/apache/batik/svggen/SVGAccuracyTest.java

Modified: xmlgraphics/batik/trunk/build.xml
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/build.xml?rev=291468&r1=291467&r2=291468&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/build.xml (original)
+++ xmlgraphics/batik/trunk/build.xml Sun Sep 25 12:51:54 2005
@@ -1163,6 +1163,7 @@
     <mkdir dir="${test-references}/svgbe/accepted-variation"/>
     <mkdir dir="${test-references}/svgbe/candidate-variation"/>
     <mkdir dir="${test-references}/svgbe/candidate-reference"/>
+    <mkdir dir="${test-references}/org/apache/batik/transcoder/wmf/candidate"/>
     <mkdir dir="${test-references}/org/apache/batik/svggen/candidate-ref" />
     <mkdir dir="${test-references}/org/apache/batik/svggen/rendering/candidate-variation" />
     <mkdir dir="${test-references}/org/apache/batik/svggen/rendering/candidate-reference" />

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/DOMGroupManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/DOMGroupManager.java?rev=291468&r1=291467&r2=291468&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/DOMGroupManager.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/DOMGroupManager.java Sun Sep 25 12:51:54 2005
@@ -260,8 +260,8 @@
      * in gc that are different from the values in referenceGc will be
      * present in the delta. Other values will no.
      */
-    protected SVGGraphicContext processDeltaGC(SVGGraphicContext gc,
-                                             SVGGraphicContext referenceGc) {
+    static SVGGraphicContext processDeltaGC(SVGGraphicContext gc,
+                                            SVGGraphicContext referenceGc) {
         Map groupDelta = processDeltaMap(gc.getGroupContext(),
                                          referenceGc.getGroupContext());
         Map graphicElementDelta = gc.getGraphicElementContext();
@@ -311,7 +311,7 @@
      * are different from values in referenceMap are place in the
      * returned delta Map.
      */
-    protected Map processDeltaMap(Map map, Map referenceMap) {
+    static Map processDeltaMap(Map map, Map referenceMap) {
         // no need to be synch => HashMap
         Map mapDelta = new HashMap();
         Iterator iter = map.keySet().iterator();

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGFont.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGFont.java?rev=291468&r1=291467&r2=291468&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGFont.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGFont.java Sun Sep 25 12:51:54 2005
@@ -162,14 +162,16 @@
      */
     public void recordFontUsage(String string, Font font) {
 
-        Font commonSizeFont = createCommonSizeFont(font);
-        String fontKey = commonSizeFont.getFamily() + commonSizeFont.getStyle();
+        Font   commonSizeFont = createCommonSizeFont(font);
+        String fontKey        = (commonSizeFont.getFamily() + 
+                                 commonSizeFont.getStyle());
         String textUsingFont = (String)fontStringMap.get(fontKey);
         if (textUsingFont == null) {
             // font has not been used before
             textUsingFont = "";
         }
         // append any new characters to textUsingFont
+        // FIXX: This is horribly inefficent, consider binary tree, Set, etc.
         char ch;
         for (int i = 0; i < string.length(); i++) {
             ch = string.charAt(i);
@@ -188,6 +190,8 @@
     private static Font createCommonSizeFont(Font font) {
         HashMap attributes = new HashMap(font.getAttributes());
         attributes.put(TextAttribute.SIZE, new Float(COMMON_FONT_SIZE));
+        // Remove Transform from font otherwise it will be applied twice.
+        attributes.remove(TextAttribute.TRANSFORM);
         return new Font(attributes);
     }
 
@@ -213,6 +217,11 @@
      * @return description of attribute values that describe the font
      */
     public SVGFontDescriptor toSVG(Font font, FontRenderContext frc) {
+        // Remove affine from FRC otherwise it will be applied twice.
+        FontRenderContext localFRC;
+        localFRC = new FontRenderContext(new AffineTransform(), 
+                                         frc.isAntiAliased(), 
+                                         frc.usesFractionalMetrics());
 
         String fontSize = "" + doubleString(font.getSize2D());
         String fontWeight = weightToSVG(font);
@@ -220,7 +229,8 @@
         String fontFamilyStr = familyToSVG(font);
 
         Font commonSizeFont = createCommonSizeFont(font);
-        String fontKey = commonSizeFont.getFamily() + commonSizeFont.getStyle();
+        String fontKey = (commonSizeFont.getFamily() + 
+                          commonSizeFont.getStyle());
 
         String textUsingFont = (String)fontStringMap.get(fontKey);
 
@@ -257,7 +267,8 @@
             Element fontFace = domFactory.createElementNS(SVG_NAMESPACE_URI,
                                                           SVG_FONT_FACE_TAG);
             String svgFontFamilyString = fontFamilyStr;
-            if (fontFamilyStr.startsWith("'") && fontFamilyStr.endsWith("'")) {
+            if (fontFamilyStr.startsWith("'") && 
+                fontFamilyStr.endsWith("'")) {
                 // get rid of the quotes
                 svgFontFamilyString
                     = fontFamilyStr.substring(1, fontFamilyStr.length()-1);
@@ -281,7 +292,8 @@
 
             int missingGlyphCode[] = new int[1];
             missingGlyphCode[0] = commonSizeFont.getMissingGlyphCode();
-            GlyphVector gv = commonSizeFont.createGlyphVector(frc, missingGlyphCode);
+            GlyphVector gv;
+            gv = commonSizeFont.createGlyphVector(localFRC, missingGlyphCode);
             Shape missingGlyphShape = gv.getGlyphOutline(0);
             GlyphMetrics gm = gv.getGlyphMetrics(0);
 
@@ -301,7 +313,7 @@
             fontDef.setAttributeNS(null, SVG_HORIZ_ADV_X_ATTRIBUTE,  "" + gm.getAdvance());
 
             // set the ascent and descent attributes
-            LineMetrics lm = commonSizeFont.getLineMetrics("By", frc);
+            LineMetrics lm = commonSizeFont.getLineMetrics("By", localFRC);
             fontFace.setAttributeNS(null, SVG_ASCENT_ATTRIBUTE, "" + lm.getAscent());
             fontFace.setAttributeNS(null, SVG_DESCENT_ATTRIBUTE, "" + lm.getDescent());
 
@@ -339,7 +351,8 @@
                     = domFactory.createElementNS(SVG_NAMESPACE_URI,
                                                  SVG_GLYPH_TAG);
 
-                GlyphVector gv = commonSizeFont.createGlyphVector(frc, ""+c);
+                GlyphVector gv;
+                gv = commonSizeFont.createGlyphVector(localFRC, ""+c);
                 Shape glyphShape = gv.getGlyphOutline(0);
                 GlyphMetrics gm = gv.getGlyphMetrics(0);
 

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGGraphics2D.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGGraphics2D.java?rev=291468&r1=291467&r2=291468&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGGraphics2D.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/SVGGraphics2D.java Sun Sep 25 12:51:54 2005
@@ -15,6 +15,7 @@
    limitations under the License.
 
  */
+
 package org.apache.batik.svggen;
 
 import java.awt.BasicStroke;
@@ -26,9 +27,11 @@
 import java.awt.Graphics2D;
 import java.awt.GraphicsConfiguration;
 import java.awt.Image;
+import java.awt.Paint;
 import java.awt.Shape;
 import java.awt.Stroke;
 import java.awt.font.GlyphVector;
+import java.awt.font.TextAttribute;
 import java.awt.font.TextLayout;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.NoninvertibleTransformException;
@@ -42,10 +45,16 @@
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.text.AttributedCharacterIterator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 
 import org.apache.batik.ext.awt.g2d.AbstractGraphics2D;
 import org.apache.batik.ext.awt.g2d.GraphicContext;
 import org.apache.batik.util.XMLConstants;
+import org.apache.batik.util.CSSConstants;
+import org.apache.batik.util.SVGConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.DocumentFragment;
 import org.w3c.dom.Element;
@@ -81,7 +90,7 @@
  * @see                org.w3c.dom.Document
  */
 public class SVGGraphics2D extends AbstractGraphics2D
-    implements Cloneable, SVGSyntax, XMLConstants, ErrorConstants {
+    implements Cloneable, SVGSyntax, XMLConstants, ErrorConstants, CSSConstants {
     /*
      * Constants definitions
      */
@@ -161,7 +170,7 @@
     public final void setSVGCanvasSize(Dimension svgCanvasSize) {
         this.svgCanvasSize = new Dimension(svgCanvasSize);
     }
-
+    
     /**
      * @return the SVGGeneratorContext used by this SVGGraphics2D instance.
      */
@@ -418,29 +427,42 @@
     /**
      * @param writer used to writer out the SVG content
      * @param useCss defines whether the output SVG should use CSS
+     * @param escaped defines if the characters will be escaped
      * style properties as opposed to plain attributes.
      */
-    public void stream(Writer writer, boolean useCss)
+    public void stream(Writer writer, boolean useCss, boolean escaped)
         throws SVGGraphics2DIOException {
         Element svgRoot = getRoot();
-        stream(svgRoot, writer, useCss);
+        stream(svgRoot, writer, useCss, escaped);
     }
 
     /**
+     * @param writer used to writer out the SVG content
+     * @param useCss defines whether the output SVG should use CSS
+     * style properties as opposed to plain attributes.
+     */
+    public void stream(Writer writer, boolean useCss)
+        throws SVGGraphics2DIOException {
+        Element svgRoot = getRoot();
+        stream(svgRoot, writer, useCss, false);
+    }    
+    
+    /**
      * @param svgRoot root element to stream out
      */
     public void stream(Element svgRoot, Writer writer)
         throws SVGGraphics2DIOException {
-        stream(svgRoot, writer, false);
+        stream(svgRoot, writer, false, false);
     }
 
     /**
      * @param svgRoot root element to stream out
      * @param writer output
      * @param useCss defines whether the output SVG should use CSS style
+     * @param escaped defines if the characters will be escaped
      * properties as opposed to plain attributes.
      */
-    public void stream(Element svgRoot, Writer writer, boolean useCss)
+    public void stream(Element svgRoot, Writer writer, boolean useCss, boolean escaped)
         throws SVGGraphics2DIOException {
         Node rootParent = svgRoot.getParentNode();
         Node nextSibling = svgRoot.getNextSibling();
@@ -465,7 +487,7 @@
             if (useCss)
                 SVGCSSStyler.style(svgDocument);
 
-            XmlWriter.writeXml(svgDocument, writer);
+            XmlWriter.writeXml(svgDocument, writer, escaped);
             writer.flush();
         } catch (SVGGraphics2DIOException e) {
             // this catch prevents from catching an SVGGraphics2DIOException
@@ -589,7 +611,7 @@
         generatorCtx.errorHandler.
             handleError(new SVGGraphics2DRuntimeException(ERR_XOR));
     }
-
+    
     /**
      * Gets the font metrics for the specified font.
      * @return    the font metrics for the specified font.
@@ -1163,58 +1185,62 @@
      * @see #setClip
      */
     public void drawString(String s, float x, float y) {
-        if (!textAsShapes) {
-
-            if (generatorCtx.svgFont) {
-                // record that the font is being used to draw this string, this is
-                // so that the SVG Font element will only create glyphs for the
-                // characters that are needed
-                domTreeManager.gcConverter.getFontConverter().recordFontUsage(s, getFont());
-            }
-
-            Font font = getFont();
-
-            // Account for the font transform if there is one
-            AffineTransform txtTxf = null;
-            AffineTransform savTxf = getTransform();
-
-            if (font != null){
-                txtTxf = font.getTransform();
-                if (txtTxf != null && !txtTxf.isIdentity()){
-                    // 
-                    // The additional transform applies about the text's origin
-                    //
-                    AffineTransform t = new AffineTransform();
-                    t.translate(x, y);
-                    t.concatenate(txtTxf);
-                    t.translate(-x, -y);
-                    this.transform(t);
-                } else {
-                    txtTxf = null;
-                }
-            }
-
-            Element text =
-                getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_TEXT_TAG);
-            text.setAttributeNS(null, SVG_X_ATTRIBUTE,
-                                generatorCtx.doubleString(x));
-            text.setAttributeNS(null, SVG_Y_ATTRIBUTE,
-                                generatorCtx.doubleString(y));
-            text.setAttributeNS(XML_NAMESPACE_URI,
-                                XML_SPACE_ATTRIBUTE,
-                                XML_PRESERVE_VALUE);
-            text.appendChild(getDOMFactory().createTextNode(s));
-            domGroupManager.addElement(text, DOMGroupManager.FILL);
-
-            if (txtTxf != null){
-                this.setTransform(savTxf);
-            }
-                
-        } else {
+        if (textAsShapes)  {
             GlyphVector gv = getFont().
                 createGlyphVector(getFontRenderContext(), s);
             drawGlyphVector(gv, x, y);
+            return;
         }
+
+        if (generatorCtx.svgFont) {
+            // record that the font is being used to draw this
+            // string, this is so that the SVG Font element will
+            // only create glyphs for the characters that are
+            // needed
+            domTreeManager.gcConverter.
+                getFontConverter().recordFontUsage(s, getFont());
+        }
+
+        Font font = getFont();            
+        // Account for the font transform if there is one           
+        AffineTransform savTxf = getTransform();
+        AffineTransform txtTxf = transformText(x, y);            
+
+        Element text =
+            getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_TEXT_TAG);
+        text.setAttributeNS(null, SVG_X_ATTRIBUTE, generatorCtx.doubleString(x));
+        text.setAttributeNS(null, SVG_Y_ATTRIBUTE, generatorCtx.doubleString(y));
+            
+        text.setAttributeNS(XML_NAMESPACE_URI,
+                            XML_SPACE_ATTRIBUTE,
+                            XML_PRESERVE_VALUE);
+        text.appendChild(getDOMFactory().createTextNode(s));
+        domGroupManager.addElement(text, DOMGroupManager.FILL);
+            
+        if (txtTxf != null){
+            this.setTransform(savTxf);
+        }                            
+    }
+    
+    private AffineTransform transformText(float x, float y) {
+        AffineTransform txtTxf = null;       
+        Font font = getFont();
+        if (font != null){
+            txtTxf = font.getTransform();
+            if (txtTxf != null && !txtTxf.isIdentity()){
+                // 
+                // The additional transform applies about the text's origin
+                //
+                AffineTransform t = new AffineTransform();
+                t.translate(x, y);
+                t.concatenate(txtTxf);
+                t.translate(-x, -y);
+                this.transform(t);
+            } else {
+                txtTxf = null;
+            }
+        }
+        return txtTxf;
     }
 
     /**
@@ -1231,11 +1257,7 @@
      * the glyphs can be rendered from right to left, in which case the
      * coordinate supplied is the location of the leftmost character
      * on the baseline.<br />
-     * 
-     * <b>Note</b>: The current implementation turns a drawString call
-     * into shapes. Therefore, the generated SVG file will be sub-optimal
-     * in terms of size and will have lost semantic (i.e., text is no
-     * longer text but shapes), but it is graphically accurate.
+     *
      *
      * @param iterator the iterator whose text is to be rendered
      * @param x the x coordinate where the iterator's text is to be rendered
@@ -1246,13 +1268,113 @@
      * @see #setComposite
      * @see #setClip
      */
-    public void drawString(AttributedCharacterIterator iterator,
-                           float x, float y) {
-        TextLayout layout = new TextLayout(iterator, getFontRenderContext());
-        layout.draw(this, x, y);
-    }
+    public void drawString(AttributedCharacterIterator ati, float x, float y) {
+        if ((textAsShapes) || (usesUnsupportedAttributes(ati))) {
+            TextLayout layout = new TextLayout(ati, getFontRenderContext());
+            layout.draw(this, x, y);
+            return;
+        }
+        // first we want if there is more than one run in this
+        // ati. This will be used to decide if we create tspan
+        // Elements under the text Element or not
+        boolean multiSpans = false;
+        if (ati.getRunLimit() < ati.getEndIndex()) multiSpans = true;        
+        Font font = getFont();        
+        
+        // create the parent text Element
+        Element text = getDOMFactory().createElementNS(SVG_NAMESPACE_URI, 
+                                                       SVG_TEXT_TAG);
+        text.setAttributeNS(null, SVG_X_ATTRIBUTE, 
+                            generatorCtx.doubleString(x));
+        text.setAttributeNS(null, SVG_Y_ATTRIBUTE, 
+                            generatorCtx.doubleString(y));
+        
+        Font  baseFont  = getFont();
+        Paint basePaint = getPaint();
 
+        // now iterate through all the runs
+        char ch = ati.first();
 
+        setTextElementFill   (ati);
+        setTextFontAttributes(ati, baseFont);
+
+        SVGGraphicContext textGC;
+        textGC = domTreeManager.getGraphicContextConverter().toSVG(gc);
+        domGroupManager.addElement(text, DOMGroupManager.FILL);
+        textGC.getContext().put(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+        textGC.getGroupContext().put(SVG_STROKE_ATTRIBUTE, SVG_NONE_VALUE);
+
+        boolean firstSpan = true;
+        AffineTransform savTxf = getTransform();
+        AffineTransform txtTxf = null;        
+        while (ch != AttributedCharacterIterator.DONE) {
+            // first get the text Element or create a child Element if
+            // we used tspans
+            Element tspan = text;
+            if (multiSpans) {
+                tspan = getDOMFactory().createElementNS
+                    (SVG_NAMESPACE_URI, SVG_TSPAN_TAG);
+                text.appendChild(tspan);
+            }
+            
+            // decorate the tspan Element : 
+            setTextElementFill(ati);
+            boolean resetTransform = setTextFontAttributes(ati, baseFont);
+
+            // management of font attributes                       
+            if (resetTransform || firstSpan) {
+                // Account for the font transform if there is one
+                txtTxf = transformText(x, y);
+                firstSpan = false;
+            }            
+
+            // retrieve the current span of text for the run
+            StringBuffer buf = new StringBuffer();
+            buf.append(ch);
+            int start = ati.getIndex();
+            int end   = ati.getRunLimit()-1;
+            for (int i=start; i<end; i++) {
+                ch = ati.next();
+                buf.append(ch);
+            }
+
+            String s = buf.toString();
+            if (generatorCtx.isEmbeddedFontsOn()) {
+                // record that the font is being used to draw this
+                // string, this is so that the SVG Font element will
+                // only create glyphs for the characters that are
+                // needed
+                getDOMTreeManager().getGraphicContextConverter().
+                    getFontConverter().recordFontUsage(s, getFont());
+            }            
+
+            // This must come after registering font usage other
+            // wise it doesn't know what chars were used.
+            SVGGraphicContext elementGC;
+            elementGC = domTreeManager.gcConverter.toSVG(gc);
+            elementGC.getGroupContext().put(SVG_STROKE_ATTRIBUTE, 
+                                            SVG_NONE_VALUE);
+
+            SVGGraphicContext deltaGC;
+            deltaGC = DOMGroupManager.processDeltaGC(elementGC, textGC);
+
+            // management of underline, strike attributes, etc..
+            setTextElementAttributes(deltaGC, ati);
+            
+            domTreeManager.getStyleHandler().
+                setStyle(tspan, deltaGC.getContext(),
+                         domTreeManager.getGeneratorContext());
+
+            tspan.appendChild(getDOMFactory().createTextNode(s));
+            if ((resetTransform || firstSpan) && (txtTxf != null)) {
+                this.setTransform(savTxf);
+            }                                
+            ch = ati.next();  // get first char of next run.
+        }
+        setFont(baseFont);
+        setPaint(basePaint);
+    }
+    
     /**
      * Fills the interior of a <code>Shape</code> using the settings of the
      * <code>Graphics2D</code> context. The rendering attributes applied
@@ -1273,6 +1395,101 @@
             domGroupManager.addElement(svgShape, DOMGroupManager.FILL);
         }
     }
+    
+    /** Set the Element Font and Size attributes, depending on the 
+     * AttributedCharacterIterator attributes.
+     */
+    private boolean setTextFontAttributes(AttributedCharacterIterator ati,
+                                          Font baseFont) {
+        boolean resetTransform = false;
+        if ((ati.getAttribute(TextAttribute.FONT) != null) ||
+            (ati.getAttribute(TextAttribute.FAMILY) != null) ||
+            (ati.getAttribute(TextAttribute.WEIGHT) != null) ||
+            (ati.getAttribute(TextAttribute.POSTURE) != null) ||
+            (ati.getAttribute(TextAttribute.SIZE) != null)) {
+            Map m = ati.getAttributes();
+            Font f = baseFont.deriveFont(m);
+            setFont(f);
+            resetTransform = true;
+        }
+
+        return resetTransform;
+    }
+    
+    /** Set the Element attributes, depending on the AttributedCharacterIterator attributes.
+     *  The following attributes are set :
+     *  <ul>
+     *  <li>underline</li>
+     *  <li>weight (bold or plain)</li>
+     *  <li>style (italic or normal)</li>
+     *  <li>justification (start, end, or middle)</li>
+     *  </ul>
+     */
+    private void setTextElementFill(AttributedCharacterIterator ati) {
+        if (ati.getAttribute(TextAttribute.FOREGROUND) != null) {
+            Color color = (Color)ati.getAttribute(TextAttribute.FOREGROUND);
+            setPaint(color);
+        }
+    }
+
+    private void setTextElementAttributes(SVGGraphicContext tspanGC, 
+                                          AttributedCharacterIterator ati) {
+        String decoration = "";
+        if (isUnderline(ati))
+            decoration += CSS_UNDERLINE_VALUE + " ";
+        if (isStrikeThrough(ati))
+            decoration += CSS_LINE_THROUGH_VALUE + " ";
+        int len = decoration.length();
+        if (len != 0)
+            tspanGC.getContext().put(CSS_TEXT_DECORATION_PROPERTY, 
+                                     decoration.substring(0, len-1));
+    }
+   
+    /** Return true if the AttributedCharacterIterator is bold (at its current position).
+     */         
+    private boolean isBold(AttributedCharacterIterator ati) {
+        Object weight = ati.getAttribute(TextAttribute.WEIGHT);
+        if (weight == null) 
+            return false;
+        if (weight.equals(TextAttribute.WEIGHT_REGULAR))
+            return false;
+        if (weight.equals(TextAttribute.WEIGHT_DEMILIGHT))
+            return false;
+        if (weight.equals(TextAttribute.WEIGHT_EXTRA_LIGHT))
+            return false;
+        if (weight.equals(TextAttribute.WEIGHT_LIGHT))
+            return false;
+        return true;
+    }
+    
+    /** Return true if the AttributedCharacterIterator is italic (at
+     * its current position).
+     */ 
+    private boolean isItalic(AttributedCharacterIterator ati) {
+        Object attr = ati.getAttribute(TextAttribute.POSTURE);
+        if (TextAttribute.POSTURE_OBLIQUE.equals(attr)) return true;
+        return false;
+    }
+
+    /** Return true if the AttributedCharacterIterator is underlined
+     * (at its current position).
+     */     
+    private boolean isUnderline(AttributedCharacterIterator ati) {
+        Object attr = ati.getAttribute(TextAttribute.UNDERLINE);
+        if (TextAttribute.UNDERLINE_ON.equals(attr)) return true;
+        // What to do about UNDERLINE_LOW_*?  Right now we don't
+        // draw them since we can't really model them...
+        else return false;
+    }
+
+    /** Return true if the AttributedCharacterIterator is striked
+     * through (at its current position).
+     */         
+    private boolean isStrikeThrough(AttributedCharacterIterator ati) {
+        Object attr = ati.getAttribute(TextAttribute.STRIKETHROUGH);
+        if (TextAttribute.STRIKETHROUGH_ON.equals(attr)) return true;
+        return false;
+    }
 
     /**
      * Returns the device configuration associated with this
@@ -1281,6 +1498,54 @@
     public GraphicsConfiguration getDeviceConfiguration(){
         // TO BE DONE.
         return null;
+    }
+
+    /* This is the list of attributes that can't currently be
+     * supported by drawString(AttributedCharacterIterator).
+     * For accuracy if any of these are present then the
+     * text is drawn as outlines.
+     */
+    protected Set unsupportedAttributes;
+    {
+        unsupportedAttributes = new HashSet();
+        unsupportedAttributes.add(TextAttribute.BACKGROUND);
+        unsupportedAttributes.add(TextAttribute.BIDI_EMBEDDING);
+        unsupportedAttributes.add(TextAttribute.CHAR_REPLACEMENT);
+        unsupportedAttributes.add(TextAttribute.JUSTIFICATION);
+        unsupportedAttributes.add(TextAttribute.RUN_DIRECTION);
+        unsupportedAttributes.add(TextAttribute.SUPERSCRIPT);
+        unsupportedAttributes.add(TextAttribute.SWAP_COLORS);
+        unsupportedAttributes.add(TextAttribute.TRANSFORM);
+        unsupportedAttributes.add(TextAttribute.WIDTH);
+    }
+
+    /**
+     * This method let's users indicate that they don't care that
+     * certain text attributes will not be properly converted to
+     * SVG, in exchange when those attributes are used they will 
+     * get real SVG text instead of paths.
+     *
+     * @param attrs The set of attrs to treat as unsupported, and
+     *              if present cause text to be drawn as paths.
+     *              If null ACI text will be rendered as text
+     *              (unless 'textAsShapes' is set).
+     */
+    public void setUnsupportedAttributes(Set attrs) {
+        if (attrs == null) unsupportedAttributes = null;
+        else               unsupportedAttributes = new HashSet(attrs);
+    }
+
+    public boolean usesUnsupportedAttributes(AttributedCharacterIterator aci){
+        if (unsupportedAttributes == null) return false;
+
+        Set      allAttrs = aci.getAllAttributeKeys();
+        Iterator iter     = allAttrs.iterator();
+        while (iter.hasNext()) {
+            if (unsupportedAttributes.contains(iter.next())) {
+                return true;
+            }
+        }
+        return false;
     }
 
 }

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/XmlWriter.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/XmlWriter.java?rev=291468&r1=291467&r2=291468&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/XmlWriter.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/svggen/XmlWriter.java Sun Sep 25 12:51:54 2005
@@ -46,7 +46,7 @@
 class XmlWriter implements SVGConstants {
 
     static private String EOL;
-    static private final String TAG_END = " />";
+    static private final String TAG_END = "/>";
     static private final String TAG_START = "</";
     static private final String SPACE = " ";
 
@@ -69,7 +69,8 @@
 
         public IndentWriter(Writer proxied){
             if (proxied == null)
-                throw new SVGGraphics2DRuntimeException(ErrorConstants.ERR_PROXY);
+                throw new SVGGraphics2DRuntimeException
+                    (ErrorConstants.ERR_PROXY);
 
             this.proxied = proxied;
         }
@@ -138,19 +139,21 @@
         }
     }
 
-    private static void writeXml(Attr attr, IndentWriter out) 
+    private static void writeXml(Attr attr, IndentWriter out, 
+                                 boolean escaped) 
         throws IOException{
         String name = attr.getName();
         out.write (name);
         out.write ("=\"");
-        writeChildrenXml(attr, out);
+        writeChildrenXml(attr, out, escaped);
         out.write ('"');
     }
 
     /**
      * Writes the attribute's value.
      */
-    private static void writeChildrenXml(Attr attr, IndentWriter out)
+    private static void writeChildrenXml(Attr attr, IndentWriter out, 
+                                         boolean escaped)
         throws IOException {
         char data[] = attr.getValue().toCharArray();
         if (data == null) return;
@@ -185,7 +188,14 @@
                 start = last + 1;
                 out.write ("&quot;"); 
                 break;
-            default:
+            default: // to be able to escape characters if allowed
+                if (escaped && (c > 0x007F)) {
+                    out.write (data, start, last - start);                    
+                    String hex = "0000"+Integer.toHexString(c);
+                    out.write("&#x"+hex.substring(hex.length()-4)+";");
+                    start = last + 1;
+                }
+                break;
             }
             last++;
         }
@@ -197,7 +207,8 @@
      * prevent illegal comments:  between consecutive dashes ("--")
      * or if the last character of the comment is a dash.
      */
-    private static void writeXml(Comment comment, IndentWriter out)
+    private static void writeXml(Comment comment, IndentWriter out, 
+                                 boolean escaped)
         throws IOException {
 
         char data[] = comment.getData().toCharArray();
@@ -233,12 +244,13 @@
         out.write ("-->");
     }
 
-    private static void writeXml(Text text, IndentWriter out) 
+    private static void writeXml(Text text, IndentWriter out, boolean escaped)
         throws IOException {
-        writeXml(text, out, false);
+        writeXml(text, out, false, escaped);
     }
 
-    private static void writeXml(Text text, IndentWriter out, boolean trimWS)
+    private static void writeXml(Text text, IndentWriter out, boolean trimWS, 
+                                 boolean escaped)
         throws IOException {
         char data[] = text.getData().toCharArray();
 
@@ -306,13 +318,22 @@
                 start = last + 1;
                 out.write ("&amp;");
                 break;
+            default: // to be able to escape characters if allowed
+                if (escaped && (c > 0x007F)) {
+                    out.write (data, start, last - start);
+                    String hex = "0000"+Integer.toHexString(c);
+                    out.write("&#x"+hex.substring(hex.length()-4)+";");
+                    start = last + 1;
+                }
+                break;
             }
             last++;
         }
         out.write (data, start, last - start);
     }
 
-    private static void writeXml(CDATASection cdataSection, IndentWriter out)
+    private static void writeXml(CDATASection cdataSection, IndentWriter out, 
+                                 boolean escaped)
         throws IOException {
         char[] data = cdataSection.getData().toCharArray();
         if (data == null) {
@@ -344,7 +365,8 @@
         out.write ("]]>");
     }
 
-    private static void writeXml(Element element, IndentWriter out)
+    private static void writeXml(Element element, IndentWriter out, 
+                                 boolean escaped)
         throws IOException, SVGGraphics2DIOException {
         out.write (TAG_START, 0, 1);    // "<"
         out.write (element.getTagName());
@@ -355,48 +377,49 @@
             for(int i=0; i<nAttr; i++){
                 Attr attr = (Attr)attributes.item(i);
                 out.write(' ');
-                writeXml(attr, out);
+                writeXml(attr, out, escaped);
             }
         }
 
+        boolean lastElem = (element.getParentNode().getLastChild()==element);
+
         //
         // Write empty nodes as "<EMPTY />" to make sure version 3
         // and 4 web browsers can read empty tag output as HTML.
         // XML allows "<EMPTY/>" too, of course.
         //
-        if (!element.hasChildNodes())
-            out.write(TAG_END, 0, 3);   // " />"
-        else  {
-            out.write(TAG_END, 2, 1);   // ">"
-            writeChildrenXml(element, out);
-            out.write (TAG_START, 0, 2);        // "</"
-            out.write (element.getTagName());
-            out.write (TAG_END, 2, 1);  // ">"
+        if (!element.hasChildNodes()) {
+            if (lastElem) 
+                out.setIndentLevel(out.getIndentLevel()-2);
+            out.printIndent ();
+            out.write(TAG_END, 0, 2);   // "/>"
+            return;
+        } 
+        Node child = element.getFirstChild();
+        out.printIndent ();
+        out.write(TAG_END, 1, 1);   // ">"
+        if ((child.getNodeType() != Node.TEXT_NODE) ||
+            (element.getLastChild() != child)) { // one text node child..
+            out.setIndentLevel(out.getIndentLevel()+2);
         }
+
+        writeChildrenXml(element, out, escaped);
+
+        out.write (TAG_START, 0, 2);        // "</"
+        out.write (element.getTagName());
+        if (lastElem) 
+            out.setIndentLevel(out.getIndentLevel()-2);
+        out.printIndent ();
+        out.write (TAG_END, 1, 1);  // ">"
     }
 
-    private static void writeChildrenXml(Element element, IndentWriter out)
+    private static void writeChildrenXml(Element element, IndentWriter out, 
+                                         boolean escaped)
         throws IOException, SVGGraphics2DIOException {
-        NodeList children = element.getChildNodes();
-        if (children == null)
-            return;
-
-        int length = children.getLength();
-        int     oldIndent = 0;
-        oldIndent = out.getIndentLevel();
-        try {
-            out.setIndentLevel(oldIndent + 2);
-            for(int i = 0; i < length; i++) {
-                if(children.item(i).getNodeType () != Node.TEXT_NODE) {
-                    out.printIndent ();
-                }
-                writeXml(children.item(i), out);
-            }
-        } finally {
-            out.setIndentLevel(oldIndent);
-            if (length > 0 && children.item(length-1).getNodeType() != Node.TEXT_NODE){
-                out.printIndent();          // for ETag
-            }
+        Node child = element.getFirstChild();
+        while (child != null) {
+            writeXml(child, out, escaped);
+            child = child.getNextSibling();
         }
     }
 
@@ -404,9 +427,10 @@
         throws IOException {
         String  encoding = null;
 
-        if (out.getProxied() instanceof OutputStreamWriter)
-            encoding =
-                java2std(((OutputStreamWriter)out.getProxied()).getEncoding());
+        if (out.getProxied() instanceof OutputStreamWriter) {
+            OutputStreamWriter osw = (OutputStreamWriter)out.getProxied();
+            encoding = java2std(osw.getEncoding());
+        }
 
         out.write ("<?xml version=\"1.0\"");
         if (encoding != null) {
@@ -416,27 +440,27 @@
         }
         out.write ("?>");
         out.write (EOL);
-        out.write (EOL);
 
         // Write DOCTYPE declaration here. Skip until specification is released.
         out.write ("<!DOCTYPE svg PUBLIC '");
         out.write (SVG_PUBLIC_ID);
-        out.write ("' '");
-        out.write (SVG_SYSTEM_ID);
-        out.write ("'");
+        out.write ("'"); out.write (EOL); 
 
-        out.write (">");
-        out.write (EOL);
+        out.write ("          '");
+        out.write (SVG_SYSTEM_ID);
+        out.write ("'"); out.write (">"); out.write (EOL);
     }
 
-    private static void writeXml(Document document, IndentWriter out)
+    private static void writeXml(Document document, IndentWriter out, 
+                                 boolean escaped)
         throws IOException, SVGGraphics2DIOException {
         writeDocumentHeader(out);
         NodeList childList = document.getChildNodes();
-        writeXml(childList, out);
+        writeXml(childList, out, escaped);
     }
 
-    private static void writeXml(NodeList childList, IndentWriter out)
+    private static void writeXml(NodeList childList, IndentWriter out, 
+                                 boolean escaped)
         throws IOException, SVGGraphics2DIOException {
         int     length = childList.getLength ();
 
@@ -444,7 +468,7 @@
             return;
         for (int i = 0; i < length; i++) {
             Node child = childList.item(i);
-            writeXml(child, out);
+            writeXml(child, out, escaped);
             out.write (EOL);
         }
     }
@@ -488,12 +512,12 @@
             return "ISO-2022-JP";
         if ("EUCJIS".equalsIgnoreCase (encodingName))
             return "EUC-JP";
-
-        // else we can't really do anything
-        return encodingName;
+                
+        // else we force UTF-8 encoding, better than nothing...
+        return "UTF-8";
     }
 
-    public static void writeXml(Node node, Writer writer)
+    public static void writeXml(Node node, Writer writer, boolean escaped)
         throws SVGGraphics2DIOException {
         try {
             IndentWriter out = null;
@@ -504,33 +528,31 @@
 
             switch (node.getNodeType()) {
             case Node.ATTRIBUTE_NODE:
-                writeXml((Attr)node, out);
+                writeXml((Attr)node, out, escaped);
                 break;
             case Node.COMMENT_NODE:
-                writeXml((Comment)node, out);
+                writeXml((Comment)node, out, escaped);
                 break;
             case Node.TEXT_NODE:
-                writeXml((Text)node, out);
+                writeXml((Text)node, out, escaped);
                 break;
             case Node.CDATA_SECTION_NODE:
-                writeXml((CDATASection)node, out);
+                writeXml((CDATASection)node, out, escaped);
                 break;
             case Node.DOCUMENT_NODE:
-                writeXml((Document)node, out);
+                writeXml((Document)node, out, escaped);
                 break;
             case Node.DOCUMENT_FRAGMENT_NODE:
                 writeDocumentHeader(out);
                 NodeList childList = node.getChildNodes();
-                writeXml(childList, out);
+                writeXml(childList, out, escaped);
                 break;
             case Node.ELEMENT_NODE:
-                writeXml((Element)node, out);
+                writeXml((Element)node, out, escaped);
                 break;
             default:
-                throw
-                    new SVGGraphics2DRuntimeException(ErrorConstants.INVALID_NODE+
-                                                      node.getClass().
-                                                      getName());
+                throw new SVGGraphics2DRuntimeException
+                    (ErrorConstants.INVALID_NODE+node.getClass().getName());
             }
         } catch (IOException io) {
             throw new SVGGraphics2DIOException(io);

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/WMFConstants.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/WMFConstants.java?rev=291468&r1=291467&r2=291468&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/WMFConstants.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/WMFConstants.java Sun Sep 25 12:51:54 2005
@@ -103,7 +103,7 @@
     public static final int META_CREATEBRUSH		  = 0x00F8;
     public static final int META_CREATEBITMAPINDIRECT	  = 0x02FD;
     public static final int META_CREATEBITMAP		  = 0x06FE;
-
+    
     public static final int META_OBJ_WHITE_BRUSH        = 0;
     public static final int META_OBJ_LTGRAY_BRUSH       = 1;
     public static final int META_OBJ_GRAY_BRUSH         = 2;
@@ -121,4 +121,209 @@
     public static final int META_OBJ_DEVICE_DEFAULT_FONT = 14;
     public static final int META_OBJ_DEFAULT_PALETTE    = 15;
     public static final int META_OBJ_SYSTEM_FIXED_FONT  = 16;
+    
+/* New StretchBlt() Modes */    
+    public static final int STRETCH_BLACKONWHITE = 1;
+    public static final int STRETCH_WHITEONBLACK = 2;
+    public static final int STRETCH_COLORONCOLOR = 3;
+    public static final int STRETCH_HALFTONE = 4;
+    public static final int STRETCH_ANDSCANS = 1;
+    public static final int STRETCH_ORSCANS = 2;
+    public static final int STRETCH_DELETESCANS = 3;    
+    
+    // new values for PATBLT value
+
+    /** new constant for PATBLT. 
+     */  
+    public static final int META_PATCOPY                = 0x00F00021;
+    /** new constant for PATBLT. 
+     */    
+    public static final int META_PATINVERT              = 0x005A0049;
+    /** new constant for PATBLT. 
+     */    
+    public static final int META_DSTINVERT              = 0x00550009;
+    /** new constant for PATBLT. 
+     */    
+    public static final int META_BLACKNESS              = 0x00000042;
+    /** new constant for PATBLT. 
+     */    
+    public static final int META_WHITENESS              = 0x00FF0062;
+    
+    // new constants for pen styles 
+    public static final int META_PS_SOLID = 0;
+    public static final int META_PS_DASH = 1;
+    public static final int META_PS_DOT = 2;
+    public static final int META_PS_DASHDOT = 3;
+    public static final int META_PS_DASHDOTDOT = 4;
+    public static final int META_PS_NULL = 5;
+    public static final int META_PS_INSIDEFRAME = 6;
+
+    // new constants for charsets 
+    
+    /** ANSI charset WMF ID.
+     */
+    public static final int META_CHARSET_ANSI = 0;
+
+    /** DEFAULT charset WMF ID.
+     */
+    public static final int META_CHARSET_DEFAULT = 1;
+
+    /** SYMBOL charset WMF ID.
+     */
+    public static final int META_CHARSET_SYMBOL = 2;
+
+    /** GREEK charset WMF ID.
+     */
+    public static final int META_CHARSET_GREEK = 161;
+
+    /** HEBREW charset WMF ID.
+     */
+    public static final int META_CHARSET_HEBREW = 177;
+
+    /** ARABIC charset WMF ID.
+     */
+    public static final int META_CHARSET_ARABIC = 178;
+
+    /** RUSSIAN (CYRILLIC) charset WMF ID.
+     */
+    public static final int META_CHARSET_RUSSIAN = 204;
+    
+    // new constants for charset names, useful for decoding and encoding text.
+
+    /** ANSI charset Java name, ie "ISO-8859-1" charset.
+     */
+    public static final String CHARSET_ANSI = "ISO-8859-1";
+
+    /** DEFAULT charset Java name, by default taken as "US-ASCII" charset.
+     */    
+    public static final String CHARSET_DEFAULT = "US-ASCII";
+
+    /** GREEK charset Java name, ie "windows-1253" charset.
+     */    
+    public static final String CHARSET_GREEK = "windows-1253";
+
+    /** CYRILLIC charset Java name, ie "windows-1251" charset.
+     */        
+    public static final String CHARSET_CYRILLIC = "windows-1251";
+
+    /** HEBREW charset Java name, ie "windows-1255" charset.
+     */            
+    public static final String CHARSET_HEBREW = "windows-1255";
+
+    /** ARABIC charset Java name, ie "windows-1256" charset.
+     */                
+    public static final String CHARSET_ARABIC = "windows-1256";    
+    
+    /** conversion from inches to Millimeters
+     */
+    public static final float INCH_TO_MM = 25.4f;
+        
+    /** number of inches default values
+     */
+    public static final int DEFAULT_INCH_VALUE = 576;
+    
+    // constants concerning map modes
+    public static final int MM_TEXT = 1;
+    public static final int MM_LOMETRIC = 2;
+    public static final int MM_HIMETRIC = 3;
+    public static final int MM_LOENGLISH = 4;
+    public static final int MM_HIENGLISH = 5;
+    public static final int MM_HITWIPS = 6;
+    public static final int MM_ISOTROPIC = 7;
+    public static final int MM_ANISOTROPIC = 8;
+    
+    // other WMF constants.
+    public static final int BS_SOLID = 0;
+    public static final int BS_HOLLOW = 1;
+    public static final int BS_NULL = 1;
+    public static final int BS_HATCHED = 2;
+    public static final int BS_PATTERN = 3;
+    public static final int BS_DIBPATTERN = 5;
+    public static final int HS_HORIZONTAL = 0;
+    public static final int HS_VERTICAL = 1;
+    public static final int HS_FDIAGONAL = 2;
+    public static final int HS_BDIAGONAL = 3;
+    public static final int HS_CROSS = 4;
+    public static final int HS_DIAGCROSS = 5;
+    public static final int DIB_RGB_COLORS = 0;
+    public static final int DIB_PAL_COLORS = 1;
+    public static final int FW_DONTCARE = 100;
+    public static final int FW_THIN = 100;
+    public static final int FW_NORMAL = 400;
+    public static final int FW_BOLD = 700;
+    public static final int FW_BLACK = 900;
+    public static final byte ANSI_CHARSET = 0;
+    public static final byte DEFAULT_CHARSET = 1;
+    public static final byte SYMBOL_CHARSET = 2;
+    public static final byte SHIFTJIS_CHARSET = -128;
+    public static final byte OEM_CHARSET = -1;
+    public static final byte OUT_DEFAULT_PRECIS = 0;
+    public static final byte OUT_STRING_PRECIS = 1;
+    public static final byte OUT_CHARACTER_PRECIS = 2;
+    public static final byte OUT_STROKE_PRECIS = 3;
+    public static final byte OUT_TT_PRECIS = 4;
+    public static final byte OUT_DEVICE_PRECIS = 5;
+    public static final byte OUT_RASTER_PRECIS = 6;
+    public static final byte CLIP_DEFAULT_PRECIS = 0;
+    public static final byte CLIP_CHARACTER_PRECIS = 1;
+    public static final byte CLIP_STROKE_PRECIS = 2;
+    public static final byte CLIP_MASK = 15;
+    public static final byte CLIP_LH_ANGLES = 16;
+    public static final byte CLIP_TT_ALWAYS = 32;
+    public static final byte DEFAULT_QUALITY = 0;
+    public static final byte DRAFT_QUALITY = 1;
+    public static final byte PROOF_QUALITY = 2;
+    public static final byte DEFAULT_PITCH = 0;
+    public static final byte FIXED_PITCH = 1;
+    public static final byte VARIABLE_PITCH = 2;
+    public static final byte FF_DONTCARE = 0;
+    public static final byte FF_ROMAN = 16;
+    public static final byte FF_SWISS = 32;
+    public static final byte FF_MODERN = 48;
+    public static final byte FF_SCRIPT = 64;
+    public static final byte FF_DECORATIVE = 80;
+    public static final int TRANSPARENT = 1;
+    public static final int OPAQUE = 2;
+    public static final int ALTERNATE = 1;
+    public static final int WINDING = 2;
+    public static final int TA_TOP = 0;
+    public static final int TA_BOTTOM = 8;
+    public static final int TA_BASELINE = 24;
+    public static final int TA_LEFT = 0;
+    public static final int TA_RIGHT = 2;
+    public static final int TA_CENTER = 6;
+    public static final int TA_NOUPDATECP = 0;
+    public static final int TA_UPDATECP = 1;
+    public static final int R2_BLACK = 1;
+    public static final int R2_NOTMERGEPEN = 2;
+    public static final int R2_MASKNOTPENNOT = 3;
+    public static final int R2_NOTCOPYPEN = 4;
+    public static final int R2_MASKPENNOT = 5;
+    public static final int R2_NOT = 6;
+    public static final int R2_XORPEN = 7;
+    public static final int R2_NOTMASKPEN = 8;
+    public static final int R2_MASKPEN = 9;
+    public static final int R2_NOTXORPEN = 10;
+    public static final int R2_NOP = 11;
+    public static final int R2_MERGENOTPEN = 12;
+    public static final int R2_COPYPEN = 13;
+    public static final int R2_MERGEPENNOT = 14;
+    public static final int R2_MERGEPEN = 15;
+    public static final int R2_WHITE = 16;
+    public static final int ETO_OPAQUE = 2;
+    public static final int ETO_CLIPPED = 4;
+    public static final int BLACKNESS = 66;
+    public static final int NOTSRCERASE = 0x1100a6;
+    public static final int NOTSRCCOPY = 0x330008;
+    public static final int SRCERASE = 0x440328;
+    public static final int DSTINVERT = 0x550009;
+    public static final int PATINVERT = 0x5a0049;
+    public static final int SRCINVERT = 0x660046;
+    public static final int SRCAND = 0x8800c6;
+    public static final int MERGEPAINT = 0xbb0226;
+    public static final int SRCCOPY = 0xcc0020;
+    public static final int SRCPAINT = 0xee0086;
+    public static final int PATCOPY = 0xf00021;
+    public static final int PATPAINT = 0xfb0a09;
+    public static final int WHITENESS = 0xff0062;        
 }

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/RecordStore.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/RecordStore.java?rev=291468&r1=291467&r2=291468&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/RecordStore.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/transcoder/wmf/tosvg/RecordStore.java Sun Sep 25 12:51:54 2005
@@ -14,7 +14,7 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 
- */
+*/
 
 package org.apache.batik.transcoder.wmf.tosvg;
 
@@ -98,7 +98,7 @@
                     b[ i ] = is.readByte();
                 }
                 String str = new String( b );
-                mr = new StringRecord( str );
+                mr = new MetaRecord.StringRecord( str );
             }
             break;