/*

   Copyright 2001,2003  The Apache Software Foundation 

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */
package org.apache.batik.svggen;

import java.awt.geom.Arc2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

import org.w3c.dom.Element;

/**
 * Utility class that converts an Arc2D object into
 * a corresponding SVG element, i.e., a path with an elliptical arc
 * and optionally lines..
 *
 * @author <a href="mailto:thomas.deweese@kodak.com">Thomas DeWeese</a>
 * @version $Id$
 */
public class SVGArc extends SVGGraphicObjectConverter {
    /**
     * Line converter used for degenerate cases
     */
    private SVGLine svgLine;

    /**
     * @param generatorContext used to build Elements
     */
    public SVGArc(SVGGeneratorContext generatorContext) {
        super(generatorContext);
    }

    /**
     * @param arc the Arc2D object to be converted
     */
    public Element toSVG(Arc2D arc) {
        if ((arc.getWidth() == 0) ||  (arc.getHeight() == 0)) {
            Line2D line = new Line2D.Double
                (arc.getX(), arc.getY(), 
                 arc.getX() + arc.getWidth(), 
                 arc.getY() + arc.getHeight());
            if (svgLine == null)
                svgLine = new SVGLine(generatorContext);
            return svgLine.toSVG(line);
        }

        Element svgPath = generatorContext.domFactory.createElementNS
            (SVG_NAMESPACE_URI, SVG_PATH_TAG);
        StringBuffer d = new StringBuffer("");

        Point2D startPt = arc.getStartPoint();
        Point2D endPt   = arc.getEndPoint();
        double  ext     = arc.getAngleExtent();
        int     type    = arc.getArcType();

        d.append(PATH_MOVE);
        d.append(doubleString(startPt.getX()));
        d.append(SPACE);
        d.append(doubleString(startPt.getY()));
        d.append(SPACE);

        d.append(PATH_ARC);
        d.append(doubleString(arc.getWidth()/2));
        d.append(SPACE);
        d.append(doubleString(arc.getHeight()/2));
        d.append(SPACE);
        d.append("0");  // no rotation with J2D arc.
        d.append(SPACE);
        if (ext > 0) { 
            // CCW sweep case, ext > 0
            if (ext > 180)  d.append("1");  // use large arc.
            else            d.append("0");  // use small arc.
            d.append(SPACE);
            d.append("0");  // sweep ccw
        } else {
            // CW sweep case, ext < 0
            if (ext < -180)  d.append("1");  // use large arc.
            else             d.append("0");  // use small arc.
            d.append(SPACE);
            d.append("1");  // sweep cw
        }

        d.append(SPACE);
        d.append(doubleString(endPt.getX()));
        d.append(SPACE);
        d.append(doubleString(endPt.getY()));

        if (type == Arc2D.CHORD) {
            d.append(PATH_CLOSE);
        } else if (type == Arc2D.PIE) {
            double cx = arc.getX()+arc.getWidth()/2;
            double cy = arc.getY()+arc.getHeight()/2;
            d.append(PATH_LINE_TO);
            d.append(SPACE);
            d.append(doubleString(cx));
            d.append(SPACE);
            d.append(doubleString(cy));
            d.append(SPACE);
            d.append(PATH_CLOSE);
        }
        svgPath.setAttributeNS(null, SVG_D_ATTRIBUTE, d.toString());
        return svgPath;
    }
}

@@ -668,24 +668,56 @@
 geom.Arc2D;%0A
+import java.awt.geom.Ellipse2D;%0A
 import java.
@@ -1095,16 +1095,17 @@
 erter %7B%0A
+%0A
     /**%0A
@@ -1190,16 +1190,114 @@
 gLine;%0A%0A
+    /**%0A     * Ellipse converter for 360 degree arcs.%0A     */%0A    private SVGEllipse svgEllipse;%0A%0A
     /**%0A
@@ -1573,60 +1573,165 @@
     
-if ((arc.getWidth() == 0) %7C%7C  (arc.getHeight() == 0)
+double ext    = arc.getAngleExtent();%0A        double width  = arc.getWidth();%0A        double height = arc.getHeight();%0A%0A        if (width == 0 %7C%7C height == 0
 ) %7B%0A
@@ -1846,30 +1846,21 @@
 etX() + 
-arc.getW
+w
 idth
-()
 , %0A     
@@ -1884,31 +1884,22 @@
 etY() + 
-arc.getH
+h
 eight
-()
 );%0A     
@@ -1925,16 +1925,18 @@
 == null)
+ %7B
 %0A       
@@ -1981,24 +1981,38 @@
 orContext);%0A
+            %7D%0A
             
@@ -2042,32 +2042,415 @@
 ne);%0A        %7D%0A%0A
+        if (ext %3E= 360 %7C%7C ext %3C= -360) %7B%0A            Ellipse2D ellipse = new Ellipse2D.Double%0A                (arc.getX(), arc.getY(),%0A                 arc.getX() + width,%0A                 arc.getY() + height);%0A            if (svgEllipse == null) %7B%0A                svgEllipse = new SVGEllipse(generatorContext);%0A            %7D%0A            return svgEllipse.toSVG(ellipse);%0A        %7D%0A%0A
         Element 
@@ -2694,56 +2694,8 @@
 ();%0A
-        double  ext     = arc.getAngleExtent();%0A
     
@@ -2969,31 +2969,24 @@
 eString(
-arc.getW
+w
 idth
-()/
+ / 
 2));%0A   
@@ -3037,32 +3037,25 @@
 eString(
-arc.getH
+h
 eight
-()/
+ / 
 2));%0A   
@@ -3962,24 +3962,19 @@
 tX()
-+arc.getW
+ + w
 idth
-()/
+ / 
 2;%0A 
@@ -4010,25 +4010,20 @@
 tY()
-+arc.getH
+ + h
 eight
-()/
+ / 
 2;%0A 

Fix for SVGGraphics2D; drawing >= 360 and <= 360 degree arcs now results in a circle element rather than a path element.