You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cf...@apache.org on 2012/10/25 21:01:49 UTC

svn commit: r1402274 [5/31] - in /incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext: ./ awt/ awt/color/ awt/font/ awt/g2d/ awt/geom/ awt/image/ awt/image/codec/ awt/image/codec/jpeg/ awt/image/codec/pn...

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/GraphicContext.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/GraphicContext.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/GraphicContext.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/GraphicContext.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,897 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.g2d;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.NoninvertibleTransformException;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Handles the attributes in a graphic context:<br>
+ * + Composite <br>
+ * + Font <br>
+ * + Paint <br>
+ * + Stroke <br>
+ * + Clip <br>
+ * + RenderingHints <br>
+ * + AffineTransform <br>
+ *
+ * @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a>
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @version $Id: GraphicContext.java 479564 2006-11-27 09:56:57Z dvholten $
+ */
+public class GraphicContext implements Cloneable{
+    /**
+     * Default Transform to be used for creating FontRenderContext.
+     */
+    protected AffineTransform defaultTransform = new AffineTransform();
+
+    /**
+     * Current AffineTransform. This is the concatenation
+     * of the original AffineTransform (i.e., last setTransform
+     * invocation) and the following transform invocations,
+     * as captured by originalTransform and the transformStack.
+     */
+    protected AffineTransform transform = new AffineTransform();
+
+    /**
+     * Transform stack
+     */
+    protected List transformStack = new ArrayList();
+
+    /**
+     * Defines whether the transform stack is valide or not.
+     * This is for use by the class clients. The client should
+     * validate the stack every time it starts using it. The
+     * stack becomes invalid when a new transform is set.
+     * @see #invalidateTransformStack()
+     * @see #isTransformStackValid
+     * @see #setTransform
+     */
+    protected boolean transformStackValid = true;
+
+    /**
+     * Current Paint
+     */
+    protected Paint paint = Color.black;
+
+    /**
+     * Current Stroke
+     */
+    protected Stroke stroke = new BasicStroke();
+
+    /**
+     * Current Composite
+     */
+    protected Composite composite = AlphaComposite.SrcOver;
+
+    /**
+     * Current clip
+     */
+    protected Shape clip = null;
+
+    /**
+     * Current set of RenderingHints
+     */
+    protected RenderingHints hints = new RenderingHints(null);
+
+    /**
+     * Current Font
+     */
+    protected Font font = new Font("sanserif", Font.PLAIN, 12);
+
+    /**
+     * Current background color.
+     */
+    protected Color background = new Color(0, 0, 0, 0);
+
+    /**
+     * Current foreground color
+     */
+    protected Color foreground = Color.black;
+
+    /**
+     * Default constructor
+     */
+    public GraphicContext() {
+        // to workaround a JDK bug
+        hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT);
+    }
+
+    /**
+     * @param defaultDeviceTransform Default affine transform applied to map the user space to the
+     *                               user space.
+     */
+    public GraphicContext(AffineTransform defaultDeviceTransform) {
+        this();
+        defaultTransform = new AffineTransform(defaultDeviceTransform);
+        transform = new AffineTransform(defaultTransform);
+        if (!defaultTransform.isIdentity())
+            transformStack.add(TransformStackElement.createGeneralTransformElement(defaultTransform));
+    }
+
+    /**
+     * @return a deep copy of this context
+     */
+    public Object clone(){
+        GraphicContext copyGc = new GraphicContext(defaultTransform);
+
+        //
+        // Now, copy each GC element in turn
+        //
+
+        // Default transform
+        /* Set in constructor */
+
+        // Transform
+        copyGc.transform = new AffineTransform(this.transform);
+
+        // Transform stack
+        copyGc.transformStack = new ArrayList( transformStack.size() );
+        for(int i=0; i<this.transformStack.size(); i++){
+            TransformStackElement stackElement =
+                (TransformStackElement)this.transformStack.get(i);
+            copyGc.transformStack.add(stackElement.clone());
+        }
+
+        // Transform stack validity
+        copyGc.transformStackValid = this.transformStackValid;
+
+        // Paint (immutable by requirement)
+        copyGc.paint = this.paint;
+
+        // Stroke (immutable by requirement)
+        copyGc.stroke = this.stroke;
+
+        // Composite (immutable by requirement)
+        copyGc.composite = this.composite;
+
+        // Clip
+        if(clip != null)
+            copyGc.clip = new GeneralPath(clip);
+        else
+            copyGc.clip = null;
+
+        // RenderingHints
+        copyGc.hints = (RenderingHints)this.hints.clone();
+
+        // Font (immutable)
+        copyGc.font = this.font;
+
+        // Background, Foreground (immutable)
+        copyGc.background = this.background;
+        copyGc.foreground = this.foreground;
+
+        return copyGc;
+    }
+
+    /**
+     * Gets this graphics context's current color.
+     * @return    this graphics context's current color.
+     * @see       java.awt.Color
+     * @see       java.awt.Graphics#setColor
+     */
+    public Color getColor(){
+        return foreground;
+    }
+
+    /**
+     * Sets this graphics context's current color to the specified
+     * color. All subsequent graphics operations using this graphics
+     * context use this specified color.
+     * @param     c   the new rendering color.
+     * @see       java.awt.Color
+     * @see       java.awt.Graphics#getColor
+     */
+    public void setColor(Color c){
+        if(c == null)
+            return;
+
+        if(paint != c)
+            setPaint(c);
+    }
+
+    /**
+     * Gets the current font.
+     * @return    this graphics context's current font.
+     * @see       java.awt.Font
+     * @see       java.awt.Graphics#setFont
+     */
+    public Font getFont(){
+        return font;
+    }
+
+    /**
+     * Sets this graphics context's font to the specified font.
+     * All subsequent text operations using this graphics context
+     * use this font.
+     * @param  font   the font.
+     * @see     java.awt.Graphics#getFont
+     */
+    public void setFont(Font font){
+        if(font != null)
+            this.font = font;
+    }
+
+    /**
+     * Returns the bounding rectangle of the current clipping area.
+     * This method refers to the user clip, which is independent of the
+     * clipping associated with device bounds and window visibility.
+     * If no clip has previously been set, or if the clip has been
+     * cleared using <code>setClip(null)</code>, this method returns
+     * <code>null</code>.
+     * The coordinates in the rectangle are relative to the coordinate
+     * system origin of this graphics context.
+     * @return      the bounding rectangle of the current clipping area,
+     *              or <code>null</code> if no clip is set.
+     * @see         java.awt.Graphics#getClip
+     * @see         java.awt.Graphics#clipRect
+     * @see         java.awt.Graphics#setClip(int, int, int, int)
+     * @see         java.awt.Graphics#setClip(Shape)
+     * @since       JDK1.1
+     */
+    public Rectangle getClipBounds(){
+        Shape c = getClip();
+        if(c==null)
+            return null;
+        else
+            return c.getBounds();
+    }
+
+
+    /**
+     * Intersects the current clip with the specified rectangle.
+     * The resulting clipping area is the intersection of the current
+     * clipping area and the specified rectangle.  If there is no
+     * current clipping area, either because the clip has never been
+     * set, or the clip has been cleared using <code>setClip(null)</code>,
+     * the specified rectangle becomes the new clip.
+     * This method sets the user clip, which is independent of the
+     * clipping associated with device bounds and window visibility.
+     * This method can only be used to make the current clip smaller.
+     * To set the current clip larger, use any of the setClip methods.
+     * Rendering operations have no effect outside of the clipping area.
+     * @param x the x coordinate of the rectangle to intersect the clip with
+     * @param y the y coordinate of the rectangle to intersect the clip with
+     * @param width the width of the rectangle to intersect the clip with
+     * @param height the height of the rectangle to intersect the clip with
+     * @see #setClip(int, int, int, int)
+     * @see #setClip(Shape)
+     */
+    public void clipRect(int x, int y, int width, int height){
+        clip(new Rectangle(x, y, width, height));
+    }
+
+
+    /**
+     * Sets the current clip to the rectangle specified by the given
+     * coordinates.  This method sets the user clip, which is
+     * independent of the clipping associated with device bounds
+     * and window visibility.
+     * Rendering operations have no effect outside of the clipping area.
+     * @param       x the <i>x</i> coordinate of the new clip rectangle.
+     * @param       y the <i>y</i> coordinate of the new clip rectangle.
+     * @param       width the width of the new clip rectangle.
+     * @param       height the height of the new clip rectangle.
+     * @see         java.awt.Graphics#clipRect
+     * @see         java.awt.Graphics#setClip(Shape)
+     * @since       JDK1.1
+     */
+    public void setClip(int x, int y, int width, int height){
+        setClip(new Rectangle(x, y, width, height));
+    }
+
+
+    /**
+     * Gets the current clipping area.
+     * This method returns the user clip, which is independent of the
+     * clipping associated with device bounds and window visibility.
+     * If no clip has previously been set, or if the clip has been
+     * cleared using <code>setClip(null)</code>, this method returns
+     * <code>null</code>.
+     * @return      a <code>Shape</code> object representing the
+     *              current clipping area, or <code>null</code> if
+     *              no clip is set.
+     * @see         java.awt.Graphics#getClipBounds()
+     * @see         java.awt.Graphics#clipRect
+     * @see         java.awt.Graphics#setClip(int, int, int, int)
+     * @see         java.awt.Graphics#setClip(Shape)
+     * @since       JDK1.1
+     */
+    public Shape getClip(){
+        try{
+            return transform.createInverse().createTransformedShape(clip);
+        }catch(NoninvertibleTransformException e){
+            return null;
+        }
+    }
+
+
+    /**
+     * Sets the current clipping area to an arbitrary clip shape.
+     * Not all objects that implement the <code>Shape</code>
+     * interface can be used to set the clip.  The only
+     * <code>Shape</code> objects that are guaranteed to be
+     * supported are <code>Shape</code> objects that are
+     * obtained via the <code>getClip</code> method and via
+     * <code>Rectangle</code> objects.  This method sets the
+     * user clip, which is independent of the clipping associated
+     * with device bounds and window visibility.
+     * @param clip the <code>Shape</code> to use to set the clip
+     * @see         java.awt.Graphics#getClip()
+     * @see         java.awt.Graphics#clipRect
+     * @see         java.awt.Graphics#setClip(int, int, int, int)
+     * @since       JDK1.1
+     */
+    public void setClip(Shape clip) {
+        if (clip != null)
+            this.clip = transform.createTransformedShape(clip);
+        else
+            this.clip = null;
+    }
+
+    /**
+     * Sets the <code>Composite</code> for the <code>Graphics2D</code> context.
+     * The <code>Composite</code> is used in all drawing methods such as
+     * <code>drawImage</code>, <code>drawString</code>, <code>draw</code>,
+     * and <code>fill</code>.  It specifies how new pixels are to be combined
+     * with the existing pixels on the graphics device during the rendering
+     * process.
+     * <p>If this <code>Graphics2D</code> context is drawing to a
+     * <code>Component</code> on the display screen and the
+     * <code>Composite</code> is a custom object rather than an
+     * instance of the <code>AlphaComposite</code> class, and if
+     * there is a security manager, its <code>checkPermission</code>
+     * method is called with an <code>AWTPermission("readDisplayPixels")</code>
+     * permission.
+     *
+     * @param comp the <code>Composite</code> object to be used for rendering
+     * @throws SecurityException
+     *         if a custom <code>Composite</code> object is being
+     *         used to render to the screen and a security manager
+     *         is set and its <code>checkPermission</code> method
+     *         does not allow the operation.
+     * @see java.awt.Graphics#setXORMode
+     * @see java.awt.Graphics#setPaintMode
+     * @see java.awt.AlphaComposite
+     */
+    public void setComposite(Composite comp){
+        this.composite = comp;
+    }
+
+
+    /**
+     * Sets the <code>Paint</code> attribute for the
+     * <code>Graphics2D</code> context.  Calling this method
+     * with a <code>null</code> <code>Paint</code> object does
+     * not have any effect on the current <code>Paint</code> attribute
+     * of this <code>Graphics2D</code>.
+     * @param paint the <code>Paint</code> object to be used to generate
+     * color during the rendering process, or <code>null</code>
+     * @see java.awt.Graphics#setColor
+     * @see java.awt.GradientPaint
+     * @see java.awt.TexturePaint
+     */
+    public void setPaint( Paint paint ){
+        if(paint == null)
+            return;
+
+        this.paint = paint;
+        if(paint instanceof Color)
+            foreground = (Color)paint;
+    }
+
+
+    /**
+     * Sets the <code>Stroke</code> for the <code>Graphics2D</code> context.
+     * @param s the <code>Stroke</code> object to be used to stroke a
+     * <code>Shape</code> during the rendering process
+     * @see BasicStroke
+     */
+    public void setStroke(Stroke s){
+        stroke = s;
+    }
+
+    /**
+     * Sets the value of a single preference for the rendering algorithms.
+     * Hint categories include controls for rendering quality and overall
+     * time/quality trade-off in the rendering process.  Refer to the
+     * <code>RenderingHints</code> class for definitions of some common
+     * keys and values.
+     * @param hintKey the key of the hint to be set.
+     * @param hintValue the value indicating preferences for the specified
+     * hint category.
+     * @see RenderingHints
+     */
+    public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue){
+        hints.put(hintKey, hintValue);
+    }
+
+
+    /**
+     * Returns the value of a single preference for the rendering algorithms.
+     * Hint categories include controls for rendering quality and overall
+     * time/quality trade-off in the rendering process.  Refer to the
+     * <code>RenderingHints</code> class for definitions of some common
+     * keys and values.
+     * @param hintKey the key corresponding to the hint to get.
+     * @return an object representing the value for the specified hint key.
+     * Some of the keys and their associated values are defined in the
+     * <code>RenderingHints</code> class.
+     * @see RenderingHints
+     */
+    public Object getRenderingHint(RenderingHints.Key hintKey){
+        return hints.get(hintKey);
+    }
+
+
+    /**
+     * Replaces the values of all preferences for the rendering
+     * algorithms with the specified <code>hints</code>.
+     * The existing values for all rendering hints are discarded and
+     * the new set of known hints and values are initialized from the
+     * specified {@link Map} object.
+     * Hint categories include controls for rendering quality and
+     * overall time/quality trade-off in the rendering process.
+     * Refer to the <code>RenderingHints</code> class for definitions of
+     * some common keys and values.
+     * @param hints the rendering hints to be set
+     * @see RenderingHints
+     */
+    public void setRenderingHints(Map hints){
+        this.hints = new RenderingHints(hints);
+    }
+
+
+    /**
+     * Sets the values of an arbitrary number of preferences for the
+     * rendering algorithms.
+     * Only values for the rendering hints that are present in the
+     * specified <code>Map</code> object are modified.
+     * All other preferences not present in the specified
+     * object are left unmodified.
+     * Hint categories include controls for rendering quality and
+     * overall time/quality trade-off in the rendering process.
+     * Refer to the <code>RenderingHints</code> class for definitions of
+     * some common keys and values.
+     * @param hints the rendering hints to be set
+     * @see RenderingHints
+     */
+    public void addRenderingHints(Map hints){
+        this.hints.putAll(hints);
+    }
+
+
+    /**
+     * Gets the preferences for the rendering algorithms.  Hint categories
+     * include controls for rendering quality and overall time/quality
+     * trade-off in the rendering process.
+     * Returns all of the hint key/value pairs that were ever specified in
+     * one operation.  Refer to the
+     * <code>RenderingHints</code> class for definitions of some common
+     * keys and values.
+     * @return a reference to an instance of <code>RenderingHints</code>
+     * that contains the current preferences.
+     * @see RenderingHints
+     */
+    public RenderingHints getRenderingHints(){
+        return hints;
+    }
+
+    /**
+     * Translates the origin of the graphics context to the point
+     * (<i>x</i>,&nbsp;<i>y</i>) in the current coordinate system.
+     * Modifies this graphics context so that its new origin corresponds
+     * to the point (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's
+     * original coordinate system.  All coordinates used in subsequent
+     * rendering operations on this graphics context will be relative
+     * to this new origin.
+     * @param  x   the <i>x</i> coordinate.
+     * @param  y   the <i>y</i> coordinate.
+     */
+    public void translate(int x, int y){
+        if(x!=0 || y!=0){
+            transform.translate(x, y);
+            transformStack.add(TransformStackElement.createTranslateElement(x, y));
+        }
+    }
+
+
+    /**
+     * Concatenates the current
+     * <code>Graphics2D</code> <code>Transform</code>
+     * with a translation transform.
+     * Subsequent rendering is translated by the specified
+     * distance relative to the previous position.
+     * This is equivalent to calling transform(T), where T is an
+     * <code>AffineTransform</code> represented by the following matrix:
+     * <pre>
+     *          [   1    0    tx  ]
+     *          [   0    1    ty  ]
+     *          [   0    0    1   ]
+     * </pre>
+     * @param tx the distance to translate along the x-axis
+     * @param ty the distance to translate along the y-axis
+     */
+    public void translate(double tx, double ty){
+        transform.translate(tx, ty);
+        transformStack.add(TransformStackElement.createTranslateElement(tx, ty));
+    }
+
+    /**
+     * Concatenates the current <code>Graphics2D</code>
+     * <code>Transform</code> with a rotation transform.
+     * Subsequent rendering is rotated by the specified radians relative
+     * to the previous origin.
+     * This is equivalent to calling <code>transform(R)</code>, where R is an
+     * <code>AffineTransform</code> represented by the following matrix:
+     * <pre>
+     *          [   cos(theta)    -sin(theta)    0   ]
+     *          [   sin(theta)     cos(theta)    0   ]
+     *          [       0              0         1   ]
+     * </pre>
+     * Rotating with a positive angle theta rotates points on the positive
+     * x axis toward the positive y axis.
+     * @param theta the angle of rotation in radians
+     */
+    public void rotate(double theta){
+        transform.rotate(theta);
+        transformStack.add(TransformStackElement.createRotateElement(theta));
+    }
+
+    /**
+     * Concatenates the current <code>Graphics2D</code>
+     * <code>Transform</code> with a translated rotation
+     * transform.  Subsequent rendering is transformed by a transform
+     * which is constructed by translating to the specified location,
+     * rotating by the specified radians, and translating back by the same
+     * amount as the original translation.  This is equivalent to the
+     * following sequence of calls:
+     * <pre>
+     *          translate(x, y);
+     *          rotate(theta);
+     *          translate(-x, -y);
+     * </pre>
+     * Rotating with a positive angle theta rotates points on the positive
+     * x axis toward the positive y axis.
+     * @param theta the angle of rotation in radians
+     * @param x x coordinate of the origin of the rotation
+     * @param y y coordinate of the origin of the rotation
+     */
+    public void rotate(double theta, double x, double y){
+        transform.rotate(theta, x, y);
+        transformStack.add(TransformStackElement.createTranslateElement(x, y));
+        transformStack.add(TransformStackElement.createRotateElement(theta));
+        transformStack.add(TransformStackElement.createTranslateElement(-x, -y));
+    }
+
+    /**
+     * Concatenates the current <code>Graphics2D</code>
+     * <code>Transform</code> with a scaling transformation
+     * Subsequent rendering is resized according to the specified scaling
+     * factors relative to the previous scaling.
+     * This is equivalent to calling <code>transform(S)</code>, where S is an
+     * <code>AffineTransform</code> represented by the following matrix:
+     * <pre>
+     *          [   sx   0    0   ]
+     *          [   0    sy   0   ]
+     *          [   0    0    1   ]
+     * </pre>
+     * @param sx the amount by which X coordinates in subsequent
+     * rendering operations are multiplied relative to previous
+     * rendering operations.
+     * @param sy the amount by which Y coordinates in subsequent
+     * rendering operations are multiplied relative to previous
+     * rendering operations.
+     */
+    public void scale(double sx, double sy){
+        transform.scale(sx, sy);
+        transformStack.add(TransformStackElement.createScaleElement(sx, sy));
+    }
+
+    /**
+     * Concatenates the current <code>Graphics2D</code>
+     * <code>Transform</code> with a shearing transform.
+     * Subsequent renderings are sheared by the specified
+     * multiplier relative to the previous position.
+     * This is equivalent to calling <code>transform(SH)</code>, where SH
+     * is an <code>AffineTransform</code> represented by the following
+     * matrix:
+     * <pre>
+     *          [   1   shx   0   ]
+     *          [  shy   1    0   ]
+     *          [   0    0    1   ]
+     * </pre>
+     * @param shx the multiplier by which coordinates are shifted in
+     * the positive X axis direction as a function of their Y coordinate
+     * @param shy the multiplier by which coordinates are shifted in
+     * the positive Y axis direction as a function of their X coordinate
+     */
+    public void shear(double shx, double shy){
+        transform.shear(shx, shy);
+        transformStack.add(TransformStackElement.createShearElement(shx, shy));
+    }
+
+    /**
+     * Composes an <code>AffineTransform</code> object with the
+     * <code>Transform</code> in this <code>Graphics2D</code> according
+     * to the rule last-specified-first-applied.  If the current
+     * <code>Transform</code> is Cx, the result of composition
+     * with Tx is a new <code>Transform</code> Cx'.  Cx' becomes the
+     * current <code>Transform</code> for this <code>Graphics2D</code>.
+     * Transforming a point p by the updated <code>Transform</code> Cx' is
+     * equivalent to first transforming p by Tx and then transforming
+     * the result by the original <code>Transform</code> Cx.  In other
+     * words, Cx'(p) = Cx(Tx(p)).  A copy of the Tx is made, if necessary,
+     * so further modifications to Tx do not affect rendering.
+     * @param Tx the <code>AffineTransform</code> object to be composed with
+     * the current <code>Transform</code>
+     * @see #setTransform
+     * @see AffineTransform
+     */
+    public void transform(AffineTransform Tx){
+        transform.concatenate(Tx);
+        transformStack.add(TransformStackElement.createGeneralTransformElement(Tx));
+    }
+
+    /**
+     * Sets the <code>Transform</code> in the <code>Graphics2D</code>
+     * context.
+     * @param Tx the <code>AffineTransform</code> object to be used in the
+     * rendering process
+     * @see #transform
+     * @see AffineTransform
+     */
+    public void setTransform(AffineTransform Tx){
+        transform = new AffineTransform(Tx);
+        invalidateTransformStack();
+        if(!Tx.isIdentity())
+            transformStack.add(TransformStackElement.createGeneralTransformElement(Tx));
+    }
+
+    /**
+     * Marks the GraphicContext's isNewTransformStack to false
+     * as a memento that the current transform stack was read and
+     * has not been reset. Only the setTransform method can
+     * override this memento.
+     */
+    public void validateTransformStack(){
+        transformStackValid = true;
+    }
+
+    /**
+     * Checks the status of the transform stack
+     */
+    public boolean isTransformStackValid(){
+        return transformStackValid;
+    }
+
+    /**
+     * @return array containing the successive transforms that
+     *         were concatenated with the original one.
+     */
+    public TransformStackElement[] getTransformStack(){
+        TransformStackElement[] stack = new TransformStackElement[transformStack.size()];
+        transformStack.toArray( stack );
+        return stack;
+    }
+
+    /**
+     * Marks the GraphicContext's isNewTransformStack to true
+     * as a memento that the current transform stack was reset
+     * since it was last read. Only validateTransformStack
+     * can override this memento
+     */
+    protected void invalidateTransformStack(){
+        transformStack.clear();
+        transformStackValid = false;
+    }
+
+    /**
+     * Returns a copy of the current <code>Transform</code> in the
+     * <code>Graphics2D</code> context.
+     * @return the current <code>AffineTransform</code> in the
+     *             <code>Graphics2D</code> context.
+     * @see #transform
+     * @see #setTransform
+     */
+    public AffineTransform getTransform(){
+        return new AffineTransform(transform);
+    }
+
+    /**
+     * Returns the current <code>Paint</code> of the
+     * <code>Graphics2D</code> context.
+     * @return the current <code>Graphics2D</code> <code>Paint</code>,
+     * which defines a color or pattern.
+     * @see #setPaint
+     * @see java.awt.Graphics#setColor
+     */
+    public Paint getPaint(){
+        return paint;
+    }
+
+
+    /**
+     * Returns the current <code>Composite</code> in the
+     * <code>Graphics2D</code> context.
+     * @return the current <code>Graphics2D</code> <code>Composite</code>,
+     *              which defines a compositing style.
+     * @see #setComposite
+     */
+    public Composite getComposite(){
+        return composite;
+    }
+
+    /**
+     * Sets the background color for the <code>Graphics2D</code> context.
+     * The background color is used for clearing a region.
+     * When a <code>Graphics2D</code> is constructed for a
+     * <code>Component</code>, the background color is
+     * inherited from the <code>Component</code>. Setting the background color
+     * in the <code>Graphics2D</code> context only affects the subsequent
+     * <code>clearRect</code> calls and not the background color of the
+     * <code>Component</code>.  To change the background
+     * of the <code>Component</code>, use appropriate methods of
+     * the <code>Component</code>.
+     * @param color the background color that isused in
+     * subsequent calls to <code>clearRect</code>
+     * @see #getBackground
+     * @see java.awt.Graphics#clearRect
+     */
+    public void setBackground(Color color){
+        if(color == null)
+            return;
+
+        background = color;
+    }
+
+
+    /**
+     * Returns the background color used for clearing a region.
+     * @return the current <code>Graphics2D</code> <code>Color</code>,
+     * which defines the background color.
+     * @see #setBackground
+     */
+    public Color getBackground(){
+        return background;
+    }
+
+    /**
+     * Returns the current <code>Stroke</code> in the
+     * <code>Graphics2D</code> context.
+     * @return the current <code>Graphics2D</code> <code>Stroke</code>,
+     *                 which defines the line style.
+     * @see #setStroke
+     */
+    public Stroke getStroke(){
+        return stroke;
+    }
+
+
+    /**
+     * Intersects the current <code>Clip</code> with the interior of the
+     * specified <code>Shape</code> and sets the <code>Clip</code> to the
+     * resulting intersection.  The specified <code>Shape</code> is
+     * transformed with the current <code>Graphics2D</code>
+     * <code>Transform</code> before being intersected with the current
+     * <code>Clip</code>.  This method is used to make the current
+     * <code>Clip</code> smaller.
+     * To make the <code>Clip</code> larger, use <code>setClip</code>.
+     * The <i>user clip</i> modified by this method is independent of the
+     * clipping associated with device bounds and visibility.  If no clip has
+     * previously been set, or if the clip has been cleared using
+     * {@link java.awt.Graphics#setClip(Shape) setClip} with a
+     * <code>null</code> argument, the specified <code>Shape</code> becomes
+     * the new user clip.
+     * @param s the <code>Shape</code> to be intersected with the current
+     *          <code>Clip</code>.  If <code>s</code> is <code>null</code>,
+     *          this method clears the current <code>Clip</code>.
+     */
+    public void clip(Shape s){
+        if (s != null)
+            s = transform.createTransformedShape(s);
+
+        if (clip != null) {
+            Area newClip = new Area(clip);
+            newClip.intersect(new Area(s));
+            clip = new GeneralPath(newClip);
+        } else {
+            clip = s;
+        }
+    }
+
+    /**
+     * Get the rendering context of the <code>Font</code> within this
+     * <code>Graphics2D</code> context.
+     * The {@link FontRenderContext}
+     * encapsulates application hints such as anti-aliasing and
+     * fractional metrics, as well as target device specific information
+     * such as dots-per-inch.  This information should be provided by the
+     * application when using objects that perform typographical
+     * formatting, such as <code>Font</code> and
+     * <code>TextLayout</code>.  This information should also be provided
+     * by applications that perform their own layout and need accurate
+     * measurements of various characteristics of glyphs such as advance
+     * and line height when various rendering hints have been applied to
+     * the text rendering.
+     *
+     * @return a reference to an instance of FontRenderContext.
+     * @see java.awt.font.FontRenderContext
+     * @see java.awt.Font#createGlyphVector(FontRenderContext,char[])
+     * @see java.awt.font.TextLayout
+     * @since     JDK1.2
+     */
+    public FontRenderContext getFontRenderContext(){
+        //
+        // Find if antialiasing should be used.
+        //
+        Object antialiasingHint = hints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
+        boolean isAntialiased = true;
+        if(antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_ON &&
+           antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT){
+
+            // If antialias was not turned off, then use the general rendering
+            // hint.
+            if(antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_OFF){
+                antialiasingHint = hints.get(RenderingHints.KEY_ANTIALIASING);
+
+                // Test general hint
+                if(antialiasingHint != RenderingHints.VALUE_ANTIALIAS_ON &&
+                   antialiasingHint != RenderingHints.VALUE_ANTIALIAS_DEFAULT){
+                    // Antialiasing was not requested. However, if it was not turned
+                    // off explicitly, use it.
+                    if(antialiasingHint == RenderingHints.VALUE_ANTIALIAS_OFF)
+                        isAntialiased = false;
+                }
+            }
+            else
+                isAntialiased = false;
+
+        }
+
+        //
+        // Find out whether fractional metrics should be used.
+        //
+        boolean useFractionalMetrics = true;
+        if(hints.get(RenderingHints.KEY_FRACTIONALMETRICS)
+           == RenderingHints.VALUE_FRACTIONALMETRICS_OFF)
+            useFractionalMetrics = false;
+
+        FontRenderContext frc = new FontRenderContext(defaultTransform,
+                                                      isAntialiased,
+                                                      useFractionalMetrics);
+        return frc;
+    }
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/GraphicContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformStackElement.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformStackElement.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformStackElement.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformStackElement.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,206 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.g2d;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * Contains a description of an elementary transform stack element,
+ * such as a rotate or translate. A transform stack element has a
+ * type and a value, which is an array of double values.<br>
+ *
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @author <a href="mailto:paul_evenblij@compuware.com">Paul Evenblij</a>
+ * @version $Id: TransformStackElement.java 478249 2006-11-22 17:29:37Z dvholten $
+ */
+public abstract class TransformStackElement implements Cloneable{
+
+    /**
+     * Transform type
+     */
+    private TransformType type;
+
+    /**
+     * Value
+     */
+    private double[] transformParameters;
+
+    /**
+     * @param type transform type
+     * @param transformParameters parameters for transform
+     */
+    protected TransformStackElement(TransformType type,
+                                    double[] transformParameters){
+        this.type = type;
+        this.transformParameters = transformParameters;
+    }
+
+    /**
+     * @return an object which is a deep copy of this one
+     */
+    public Object clone() {
+        TransformStackElement newElement = null;
+
+        // start with a shallow copy to get our implementations right
+        try {
+            newElement = (TransformStackElement) super.clone();
+        } catch(java.lang.CloneNotSupportedException ex) {}
+
+        // now deep copy the parameter array
+        double[] transformParameters = new double[this.transformParameters.length];
+        System.arraycopy(this.transformParameters, 0, transformParameters, 0, transformParameters.length);
+        newElement.transformParameters = transformParameters;
+        return newElement;
+    }
+
+    /*
+     * Factory methods
+     */
+
+    public static TransformStackElement createTranslateElement(double tx,
+                                                               double ty){
+        return new TransformStackElement(TransformType.TRANSLATE,
+                                         new double[]{ tx, ty }) {
+                boolean isIdentity(double[] parameters) {
+                    return parameters[0] == 0 && parameters[1] == 0;
+                }
+            };
+    }
+
+    public static TransformStackElement createRotateElement(double theta){
+        return new TransformStackElement(TransformType.ROTATE,
+                                         new double[]{ theta }) {
+                boolean isIdentity(double[] parameters) {
+                    return Math.cos(parameters[0]) == 1;
+                }
+            };
+    }
+
+    public static TransformStackElement createScaleElement(double scaleX,
+                                                           double scaleY){
+        return new TransformStackElement(TransformType.SCALE,
+                                         new double[]{ scaleX, scaleY }) {
+                boolean isIdentity(double[] parameters) {
+                    return parameters[0] == 1 && parameters[1] == 1;
+                }
+            };
+    }
+
+    public static TransformStackElement createShearElement(double shearX,
+                                                           double shearY){
+        return new TransformStackElement(TransformType.SHEAR,
+                                         new double[]{ shearX, shearY }) {
+                boolean isIdentity(double[] parameters) {
+                    return parameters[0] == 0 && parameters[1] == 0;
+                }
+            };
+    }
+
+    public static TransformStackElement createGeneralTransformElement
+        (AffineTransform txf){
+        double[] matrix = new double[6];
+        txf.getMatrix(matrix);
+        return new TransformStackElement(TransformType.GENERAL, matrix) {
+                boolean isIdentity(double[] m) {
+                    return (m[0] == 1 && m[2] == 0 && m[4] == 0 &&
+                            m[1] == 0 && m[3] == 1 && m[5] == 0);
+                }
+            };
+    }
+
+    /**
+     * Implementation should determine if the parameter list represents
+     * an identity transform, for the instance transform type.
+     */
+    abstract boolean isIdentity(double[] parameters);
+
+    /**
+     * @return true iff this transform is the identity transform
+     */
+    public boolean isIdentity() {
+        return isIdentity(transformParameters);
+    }
+
+    /**
+     * @return array of values containing this transform element's parameters
+     */
+    public double[] getTransformParameters(){
+        return transformParameters;
+    }
+
+    /**
+     * @return this transform type
+     */
+    public TransformType getType(){
+        return type;
+    }
+
+    /*
+     * Concatenation utility. Requests this transform stack element
+     * to concatenate with the input stack element. Only elements
+     * of the same types are concatenated. For example, if this
+     * element represents a translation, it will concatenate with
+     * another translation, but not with any other kind of
+     * stack element.
+     * @param stackElement element to be concatenated with this one.
+     * @return true if the input stackElement was concatenated with
+     *         this one. False otherwise.
+     */
+    public boolean concatenate(TransformStackElement stackElement){
+        boolean canConcatenate = false;
+
+        if(type.toInt() == stackElement.type.toInt()){
+            canConcatenate = true;
+            switch(type.toInt()){
+            case TransformType.TRANSFORM_TRANSLATE:
+                transformParameters[0] += stackElement.transformParameters[0];
+                transformParameters[1] += stackElement.transformParameters[1];
+                break;
+            case TransformType.TRANSFORM_ROTATE:
+                transformParameters[0] += stackElement.transformParameters[0];
+                break;
+            case TransformType.TRANSFORM_SCALE:
+                transformParameters[0] *= stackElement.transformParameters[0];
+                transformParameters[1] *= stackElement.transformParameters[1];
+                break;
+            case TransformType.TRANSFORM_GENERAL:
+                transformParameters
+                    = matrixMultiply(transformParameters,
+                                     stackElement.transformParameters);
+                break;
+            default:
+                canConcatenate = false;
+            }
+        }
+
+        return canConcatenate;
+    }
+
+    /**
+     *  Multiplies two 2x3 matrices of double precision values
+     */
+    private double[] matrixMultiply(double[] matrix1, double[] matrix2) {
+        double[] product = new double[6];
+        AffineTransform transform1 = new AffineTransform(matrix1);
+        transform1.concatenate(new AffineTransform(matrix2));
+        transform1.getMatrix(product);
+        return product;
+    }
+
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformStackElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformType.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformType.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformType.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformType.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,111 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+
+package org.apache.flex.forks.batik.ext.awt.g2d;
+
+/**
+ * Enumeration for transformation types.
+ *
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @version $Id: TransformType.java 504084 2007-02-06 11:24:46Z dvholten $
+ */
+public class TransformType{
+    /*
+     * Transform type constants
+     */
+    public static final int TRANSFORM_TRANSLATE = 0;
+    public static final int TRANSFORM_ROTATE = 1;
+    public static final int TRANSFORM_SCALE = 2;
+    public static final int TRANSFORM_SHEAR = 3;
+    public static final int TRANSFORM_GENERAL = 4;
+
+    /**
+     * Strings describing the elementary transforms
+     */
+    public static final String TRANSLATE_STRING = "translate";
+    public static final String ROTATE_STRING = "rotate";
+    public static final String SCALE_STRING = "scale";
+    public static final String SHEAR_STRING = "shear";
+    public static final String GENERAL_STRING = "general";
+
+    /**
+     * TransformType values
+     */
+    public static final TransformType TRANSLATE = new TransformType(TRANSFORM_TRANSLATE, TRANSLATE_STRING);
+    public static final TransformType ROTATE = new TransformType(TRANSFORM_ROTATE, ROTATE_STRING);
+    public static final TransformType SCALE = new TransformType(TRANSFORM_SCALE, SCALE_STRING);
+    public static final TransformType SHEAR = new TransformType(TRANSFORM_SHEAR, SHEAR_STRING);
+    public static final TransformType GENERAL = new TransformType(TRANSFORM_GENERAL, GENERAL_STRING);
+
+    private String desc;
+    private int val;
+
+    /**
+     * Constructor is private so that no instances other than
+     * the ones in the enumeration can be created.
+     * @see #readResolve
+     */
+    private TransformType(int val, String desc){
+        this.desc = desc;
+        this.val = val;
+    }
+
+    /**
+     * @return description
+     */
+    public String toString(){
+        return desc;
+    }
+
+    /**
+     * Convenience for enumeration switching.
+     * That is,
+     * <pre>
+     *   switch(transformType.toInt()){
+     *       case TransformType.TRANSFORM_TRANSLATE:
+     *        ....
+     *       case TransformType.TRANSFORM_ROTATE:
+     * </pre>
+     */
+    public int toInt(){
+        return val;
+    }
+
+    /**
+     *  This is called by the serialization code before it returns an unserialized
+     * object. To provide for unicity of instances, the instance that was read
+     * is replaced by its static equivalent
+     */
+    public Object readResolve() {
+        switch(val){
+        case TRANSFORM_TRANSLATE:
+            return TransformType.TRANSLATE;
+        case TRANSFORM_ROTATE:
+            return TransformType.ROTATE;
+        case TRANSFORM_SCALE:
+            return TransformType.SCALE;
+        case TRANSFORM_SHEAR:
+            return TransformType.SHEAR;
+        case TRANSFORM_GENERAL:
+            return TransformType.GENERAL;
+        default:
+            throw new Error("Unknown TransformType value:" + val );
+        }
+    }
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/TransformType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/package.html
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/package.html?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/package.html (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/package.html Thu Oct 25 19:01:43 2012
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+"http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+  <head>
+    <title>Abstract Graphics2D Package</title>
+  </head>
+  <body>
+    Provides an API for subclassing the <code>java.awt.Graphics2D</code>
+    class in order to translate Java 2D primitives into another graphic
+    format.
+  </body>
+</html>

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/g2d/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/AbstractSegment.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/AbstractSegment.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/AbstractSegment.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/AbstractSegment.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,327 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.geom;
+
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+
+/**
+ * An abstract class for path segments.
+ *
+ * @version $Id: AbstractSegment.java 478249 2006-11-22 17:29:37Z dvholten $
+ */
+public abstract class AbstractSegment implements Segment {
+
+    protected abstract int findRoots(double y, double [] roots);
+
+    public Segment.SplitResults split(double y) {
+        double [] roots = { 0, 0, 0 };
+        int numSol = findRoots(y, roots);
+        if (numSol == 0) return null; // No split
+
+        Arrays.sort(roots, 0, numSol);
+        double [] segs = new double[numSol+2];
+        int numSegments=0;
+        segs[numSegments++] = 0;
+        for (int i=0; i<numSol; i++) {
+            double r = roots[i];
+            if (r <= 0.0) continue;
+            if (r >= 1.0) break;
+            if (segs[numSegments-1] != r)
+                segs[numSegments++] = r;
+        }
+        segs[numSegments++] = 1.0;
+
+        if (numSegments == 2) return null;
+        // System.err.println("Y: " + y + "#Seg: " + numSegments +
+        //                    " Seg: " + this);
+
+        Segment [] parts = new Segment[numSegments];
+        double pT = 0.0;
+        int pIdx = 0;
+        boolean firstAbove=false, prevAbove=false;
+        for (int i=1; i<numSegments; i++) {
+            // System.err.println("Segs: " + segs[i-1]+", "+segs[i]);
+            parts[pIdx] = getSegment(segs[i-1], segs[i]);
+            Point2D.Double pt = parts[pIdx].eval(0.5);
+            // System.err.println("Pt: " + pt);
+            if (pIdx == 0) {
+                pIdx++;
+                firstAbove = prevAbove = (pt.y < y);
+                continue;
+            }
+            boolean above = (pt.y < y);
+            if (prevAbove == above) {
+                // Merge segments
+                parts[pIdx-1] = getSegment(pT, segs[i]);
+            } else {
+                pIdx++;
+                pT=segs[i-1];
+                prevAbove = above;
+            }
+        }
+        if (pIdx == 1) return null;
+        Segment [] below, above;
+        if (firstAbove) {
+            above = new Segment[(pIdx+1)/2];
+            below = new Segment[pIdx/2];
+        } else {
+            above = new Segment[pIdx/2];
+            below = new Segment[(pIdx+1)/2];
+        }
+        int ai=0, bi=0;
+        for (int i=0; i<pIdx; i++) {
+            if (firstAbove) above[ai++] = parts[i];
+            else            below[bi++] = parts[i];
+            firstAbove = !firstAbove;
+        }
+        return new SplitResults(below, above);
+    }
+
+    public Segment splitBefore(double t) {
+        return getSegment(0.0, t);
+    }
+
+    public Segment splitAfter(double t) {
+        return getSegment(t, 1.0);
+    }
+
+    // Doubles have 48bit precision
+    static final double eps = 1/(double)(1L<<48);
+    static final double tol = 4.0*eps;
+
+    public static int solveLine(double a, double b,
+                                 double [] roots) {
+        if (a == 0) {
+            if (b != 0)
+                // No intersection.
+                return 0;
+            // All pts intersect just return 0.
+            roots[0] = 0;
+            return 1;
+        }
+
+        roots[0] = -b/a;
+        return 1;
+    }
+
+    public static int solveQuad(double a, double b, double c,
+                                 double [] roots) {
+        // System.err.println("Quad: " + a +"t^2 + " + b +"t + " + c);
+        if (a == 0) {
+            // no square term.
+            return solveLine(b, c, roots);
+        }
+
+        double det = b*b-4*a*c;
+        // System.err.println("Det: " + det);
+
+        if (Math.abs(det) <= tol*b*b) {
+            // one real root (det doesn't contain any useful info)
+            roots[0] =  -b/(2*a);
+            return 1;
+        }
+
+        if (det < 0)
+            return 0; // No real roots
+
+        // Two real roots
+        det = Math.sqrt(det);
+        double w = -(b + matchSign(det, b));
+        roots[0] = (2*c)/w;
+        roots[1] = w/(2*a);
+        return 2;
+    }
+
+    public static double matchSign(double a, double b) {
+        if (b < 0) return (a < 0)?a:-a;
+        return (a > 0)?a:-a;
+    }
+
+    public static int solveCubic(double a3, double a2,
+                                  double a1, double a0,
+                                  double [] roots) {
+
+        // System.err.println("Cubic: " + a3 + "t^3 + " +
+        //                    a2 +"t^2 + " +
+        //                    a1 +"t + " + a0);
+
+        double [] dRoots = { 0, 0};
+        int dCnt = solveQuad(3*a3, 2*a2, a1, dRoots);
+        double [] yVals = {0, 0, 0, 0};
+        double [] tVals = {0, 0, 0, 0};
+        int yCnt=0;
+        yVals[yCnt]   = a0;
+        tVals[yCnt++] = 0;
+        double r;
+        switch (dCnt) {
+        case 1:
+            r = dRoots[0];
+            if ((r > 0) && (r < 1)) {
+                yVals[yCnt]   = ((a3*r+a2)*r+a1)*r+a0;
+                tVals[yCnt++] = r;
+            }
+            break;
+        case 2:
+            if (dRoots[0] > dRoots[1]) {
+                double t  = dRoots[0];
+                dRoots[0] = dRoots[1];
+                dRoots[1] = t;
+            }
+            r = dRoots[0];
+            if ((r > 0) && (r < 1)) {
+                yVals[yCnt]   = ((a3*r+a2)*r+a1)*r+a0;
+                tVals[yCnt++] = r;
+            }
+            r = dRoots[1];
+            if ((r > 0) && (r < 1)) {
+                yVals[yCnt]   = ((a3*r+a2)*r+a1)*r+a0;
+                tVals[yCnt++] = r;
+            }
+            break;
+        default: break;
+        }
+        yVals[yCnt]   = a3+a2+a1+a0;
+        tVals[yCnt++] = 1.0;
+
+        int ret=0;
+        for (int i=0; i<yCnt-1; i++) {
+            double y0 = yVals[i],   t0 = tVals[i];
+            double y1 = yVals[i+1], t1 = tVals[i+1];
+            if ((y0 < 0) && (y1 < 0)) continue;
+            if ((y0 > 0) && (y1 > 0)) continue;
+
+            if (y0 > y1) { // swap so y0 < 0 and y1 > 0
+                double t;
+                t = y0; y0=y1; y1=t;
+                t = t0; t0=t1; t1=t;
+            }
+
+            if (-y0 < tol*y1) { roots[ret++] = t0;      continue; }
+            if (y1 < -tol*y0) { roots[ret++] = t1; i++; continue; }
+
+            double epsZero = tol*(y1-y0);
+            int cnt;
+            for (cnt=0; cnt<20; cnt++) {
+                double dt = t1-t0;
+                double dy = y1-y0;
+                // double t = (t0+t1)/2;
+                // double t= t0+Math.abs(y0/dy)*dt;
+                // This tends to make sure that we come up
+                // a little short each time this generaly allows
+                // you to eliminate as much of the range as possible
+                // without overshooting (in which case you may eliminate
+                // almost nothing).
+                double t= t0+(Math.abs(y0/dy)*99+.5)*dt/100;
+                double v = ((a3*t+a2)*t+a1)*t+a0;
+                if (Math.abs(v) < epsZero) {
+                    roots[ret++] = t; break;
+                }
+                if (v < 0) { t0 = t; y0=v;}
+                else       { t1 = t; y1=v;}
+            }
+            if (cnt == 20)
+                roots[ret++] = (t0+t1)/2;
+        }
+        return ret;
+    }
+
+    /*
+    public static void check(Segment seg, float y, PrintStream ps) {
+        ps.println("<path fill=\"none\" stroke=\"black\" " +
+                   " stroke-width=\"3\" d=\"" + seg + "\"/>");
+
+        ps.println("<line x1=\"-1000\" y1=\""+y+
+                   "\" x2=\"1000\" y2=\""+y+"\" fill=\"none\" stroke=\"orange\"/>\n");
+
+        SplitResults sr = seg.split(y);
+        if (sr == null) return;
+        Segment [] above = sr.getAbove();
+        Segment [] below = sr.getBelow();
+        for (int i=0; i<above.length; i++) {
+            ps.println("<path fill=\"none\" stroke=\"blue\" " +
+                       " stroke-width=\"2.5\" " +
+                       " d=\"" + above[i] + "\"/>");
+        }
+        for (int i=0; i<below.length; i++) {
+            ps.println("<path fill=\"none\" stroke=\"red\" " +
+                       " stroke-width=\"2\" " +
+                       "d=\"" + below[i] + "\"/>");
+        }
+    }
+    public static void main(String [] args) {
+        PrintStream ps;
+        double [] roots = { 0, 0, 0 };
+        int n = solveCubic (-0.10000991821289062, 9.600013732910156,
+                            -35.70000457763672, 58.0, roots);
+        for (int i=0; i<n; i++)
+            System.err.println("Root: " + roots[i]);
+        Cubic c;
+        c = new Cubic(new Point2D.Double(153.6999969482422,5.099999904632568),
+                      new Point2D.Double(156.6999969482422,4.099999904632568),
+                      new Point2D.Double(160.39999389648438,2.3999998569488525),
+                      new Point2D.Double(164.6999969482422,0.0));
+        c.split(0);
+
+        c = new Cubic(new Point2D.Double(24.899999618530273,23.10000228881836),
+                      new Point2D.Double(41.5,8.399999618530273),
+                      new Point2D.Double(64.69999694824219,1.0),
+                      new Point2D.Double(94.5999984741211,1.0));
+        c.split(0);
+
+        try {
+            ps = new PrintStream(new FileOutputStream(args[0]));
+        } catch(java.io.IOException ioe) {
+            ioe.printStackTrace();
+            return;
+        }
+
+        ps.println("<?xml version=\"1.0\" standalone=\"no\"?>\n" +
+                   "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\n" +
+                   "\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n" +
+                   "<svg width=\"450\" height=\"500\"\n" +
+                   "     viewBox=\"-100 -100 450 500\"\n" +
+                   "     xmlns=\"http://www.w3.org/2000/svg\"\n" +
+                   "     xmlns:xlink=\"http://www.w3.org/1999/xlink\">");
+
+        check(new Cubic(new Point2D.Double(0, 0),
+                        new Point2D.Double(100, 100),
+                        new Point2D.Double(-50, 100),
+                        new Point2D.Double(50, 0)), 40, ps);
+
+        check(new Cubic(new Point2D.Double(100, 0),
+                        new Point2D.Double(200, 100),
+                        new Point2D.Double(50, -50),
+                        new Point2D.Double(150, 30)), 20, ps);
+
+        check(new Cubic(new Point2D.Double(200, 0),
+                        new Point2D.Double(300, 100),
+                        new Point2D.Double(150, 100),
+                        new Point2D.Double(250, 0)), 75, ps);
+
+        check(new Quadradic(new Point2D.Double(0, 100),
+                            new Point2D.Double(50,150),
+                            new Point2D.Double(10,100)), 115, ps);
+
+        check(new Linear(new Point2D.Double(100, 100),
+                         new Point2D.Double(150,150)), 115, ps);
+        ps.println("</svg>");
+    }
+    */
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/AbstractSegment.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/Cubic.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/Cubic.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/Cubic.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/Cubic.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,422 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+package org.apache.flex.forks.batik.ext.awt.geom;
+
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.QuadCurve2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * A class representing a cubic path segment.
+ *
+ * @version $Id: Cubic.java 478249 2006-11-22 17:29:37Z dvholten $
+ */
+public class Cubic extends AbstractSegment {
+
+    public Point2D.Double p1, p2, p3, p4;
+    public Cubic() {
+        p1 = new Point2D.Double();
+        p2 = new Point2D.Double();
+        p3 = new Point2D.Double();
+        p4 = new Point2D.Double();
+    }
+    public Cubic(double x1, double y1,  double x2, double y2,
+                 double x3, double y3,  double x4, double y4) {
+        p1 = new Point2D.Double(x1, y1);
+        p2 = new Point2D.Double(x2, y2);
+        p3 = new Point2D.Double(x3, y3);
+        p4 = new Point2D.Double(x4, y4);
+    }
+
+    public Cubic(Point2D.Double p1, Point2D.Double p2,
+                 Point2D.Double p3, Point2D.Double p4) {
+        this.p1 = p1;
+        this.p2 = p2;
+        this.p3 = p3;
+        this.p4 = p4;
+    }
+
+    public Object clone() {
+        return new Cubic(new Point2D.Double(p1.x, p1.y),
+                         new Point2D.Double(p2.x, p2.y),
+                         new Point2D.Double(p3.x, p3.y),
+                         new Point2D.Double(p4.x, p4.y));
+    }
+
+    public Segment reverse() {
+        return new Cubic(new Point2D.Double(p4.x, p4.y),
+                         new Point2D.Double(p3.x, p3.y),
+                         new Point2D.Double(p2.x, p2.y),
+                         new Point2D.Double(p1.x, p1.y));
+    }
+
+    private void getMinMax(double p1, double p2,
+                           double p3, double p4,
+                           double [] minMax) {
+        if (p4 > p1){
+            minMax[0] = p1; minMax[1] = p4;
+        } else {
+            minMax[0] = p4; minMax[1] = p1;
+        }
+
+        double c0 = 3*(p2-p1);
+        double c1 = 6*(p3-p2);
+        double c2 = 3*(p4-p3);
+        double [] eqn = { c0, c1-2*c0, c2-c1+c0 };
+        int roots = QuadCurve2D.solveQuadratic(eqn);
+        for (int r=0; r<roots; r++) {
+            double tv = eqn[r];
+            if ((tv <= 0) || (tv >= 1)) continue;
+            tv = ((1-tv)*(1-tv)*(1-tv)*p1 +
+                    3*tv*(1-tv)*(1-tv)*p2 +
+                    3*tv*tv*(1-tv)*p3 +
+                    tv*tv*tv*p4);
+            if      (tv < minMax[0]) minMax[0] = tv;
+            else if (tv > minMax[1]) minMax[1] = tv;
+        }
+    }
+    public double minX() {
+        double [] minMax = {0, 0};
+        getMinMax(p1.x, p2.x, p3.x, p4.x, minMax);
+        return minMax[0];
+    }
+    public double maxX() {
+        double [] minMax = {0, 0};
+        getMinMax(p1.x, p2.x, p3.x, p4.x, minMax);
+        return minMax[1];
+    }
+    public double minY() {
+        double [] minMax = {0, 0};
+        getMinMax(p1.y, p2.y, p3.y, p4.y, minMax);
+        return minMax[0];
+    }
+    public double maxY() {
+        double [] minMax = {0, 0};
+        getMinMax(p1.y, p2.y, p3.y, p4.y, minMax);
+        return minMax[1];
+    }
+
+    public Rectangle2D getBounds2D() {
+        double [] minMaxX = {0, 0};
+        getMinMax(p1.x, p2.x, p3.x, p4.x, minMaxX);
+        double [] minMaxY = {0, 0};
+        getMinMax(p1.y, p2.y, p3.y, p4.y, minMaxY);
+
+        return new Rectangle2D.Double
+            (minMaxX[0], minMaxY[0],
+             minMaxX[1]-minMaxX[0], minMaxY[1]-minMaxY[0]);
+    }
+
+    protected int findRoots(double y, double [] roots) {
+        double [] eqn = { p1.y-y, 3*(p2.y-p1.y), 3*(p1.y-2*p2.y+p3.y),
+                          3*p2.y-p1.y+p4.y-3*p3.y };
+        return CubicCurve2D.solveCubic(eqn, roots);
+        // return solveCubic(eqn[3], eqn[2], eqn[1], eqn[0], roots);
+    }
+
+    public Point2D.Double evalDt(double t) {
+        double x = 3*(  (p2.x-p1.x)*(1-t)*(1-t) +
+                      2*(p3.x-p2.x)*(1-t)*t +
+                        (p4.x-p3.x)*t*t);
+        double y = 3*(  (p2.y-p1.y)*(1-t)*(1-t) +
+                      2*(p3.y-p2.y)*(1-t)*t +
+                        (p4.y-p3.y)*t*t);
+        return new Point2D.Double(x, y);
+    }
+
+
+    public Point2D.Double eval(double t) {
+        double x = ((1-t)*(1-t)*(1-t)*p1.x +
+                    3*(t* (1-t)*(1-t)*p2.x +
+                       t* t*    (1-t)*p3.x) +
+                    t*t*t            *p4.x);
+        double y = ((1-t)*(1-t)*(1-t)*p1.y +
+                    3*(t* (1-t)*(1-t)*p2.y +
+                       t* t*    (1-t)*p3.y) +
+                    t*t*t            *p4.y);
+        return new Point2D.Double(x, y);
+    }
+
+    /**
+     * Subdivides this Cubic curve into two curves at t = 0.5.
+     * can be done with getSegment but this is more efficent.
+     * @param s0 if non-null contains portion of curve from  0->.5
+     * @param s1 if non-null contains portion of curve from .5->1
+     */
+    public void subdivide(Segment s0, Segment s1) {
+        Cubic c0=null, c1=null;
+        if (s0 instanceof Cubic) c0 = (Cubic)s0;
+        if (s1 instanceof Cubic) c1 = (Cubic)s1;
+        subdivide(c0, c1);
+    }
+
+    /**
+     * Subdivides this Cubic curve into two curves at given t.
+     * @param s0 if non-null contains portion of curve from 0->t.
+     * @param s1 if non-null contains portion of curve from t->1.
+     */
+    public void subdivide(double t, Segment s0, Segment s1) {
+        Cubic c0=null, c1=null;
+        if (s0 instanceof Cubic) c0 = (Cubic)s0;
+        if (s1 instanceof Cubic) c1 = (Cubic)s1;
+        subdivide(t, c0, c1);
+    }
+
+    /**
+     * Subdivides this Cubic curve into two curves at t = 0.5.
+     * can be done with getSegment but this is more efficent.
+     * @param c0 if non-null contains portion of curve from  0->.5
+     * @param c1 if non-null contains portion of curve from .5->1
+     */
+    public void subdivide(Cubic c0, Cubic c1) {
+        if ((c0 == null) && (c1 == null)) return;
+
+        double npX = (p1.x+3*(p2.x+p3.x)+p4.x)*0.125;
+        double npY = (p1.y+3*(p2.y+p3.y)+p4.y)*0.125;
+
+        double npdx = ((p2.x-p1.x)+2*(p3.x-p2.x)+(p4.x-p3.x))*0.125;
+        double npdy = ((p2.y-p1.y)+2*(p3.y-p2.y)+(p4.y-p3.y))*0.125;
+
+        if (c0 != null) {
+            c0.p1.x = p1.x;
+            c0.p1.y = p1.y;
+            c0.p2.x = (p2.x+p1.x)*0.5;
+            c0.p2.y = (p2.y+p1.y)*0.5;
+
+            c0.p3.x = npX-npdx;
+            c0.p3.y = npY-npdy;
+            c0.p4.x = npX;
+            c0.p4.y = npY;
+        }
+
+        if (c1 != null) {
+            c1.p1.x = npX;
+            c1.p1.y = npY;
+            c1.p2.x = npX+npdx;
+            c1.p2.y = npY+npdy;
+
+            c1.p3.x = (p4.x+p3.x)*0.5;
+            c1.p3.y = (p4.y+p3.y)*0.5;
+            c1.p4.x = p4.x;
+            c1.p4.y = p4.y;
+        }
+    }
+
+    /**
+     * Subdivides this Cubic curve into two curves at given t.
+     * @param c0 if non-null contains portion of curve from 0->t.
+     * @param c1 if non-null contains portion of curve from t->1.
+     */
+    public void subdivide(double t, Cubic c0, Cubic c1) {
+        if ((c0 == null) && (c1 == null)) return;
+
+        Point2D.Double np = eval(t);
+        Point2D.Double npd = evalDt(t);
+
+        if (c0 != null) {
+            c0.p1.x = p1.x;
+            c0.p1.y = p1.y;
+            c0.p2.x = (p2.x+p1.x)*t;
+            c0.p2.y = (p2.y+p1.y)*t;
+
+            c0.p3.x = np.x-(npd.x*t/3);
+            c0.p3.y = np.y-(npd.y*t/3);
+            c0.p4.x = np.x;
+            c0.p4.y = np.y;
+        }
+
+        if (c1 != null) {
+            c1.p1.x = np.x;
+            c1.p1.y = np.y;
+            c1.p2.x = np.x+(npd.x*(1-t)/3);
+            c1.p2.y = np.y+(npd.y*(1-t)/3);
+
+            c1.p3.x = (p4.x+p3.x)*(1-t);
+            c1.p3.y = (p4.y+p3.y)*(1-t);
+            c1.p4.x = p4.x;
+            c1.p4.y = p4.y;
+        }
+    }
+
+    public Segment getSegment(double t0, double t1) {
+        double dt = t1-t0;
+        Point2D.Double np1 = eval(t0);
+        Point2D.Double dp1 = evalDt(t0);
+        Point2D.Double np2 = new Point2D.Double(np1.x+dt*dp1.x/3,
+                                                np1.y+dt*dp1.y/3);
+
+        Point2D.Double np4 = eval(t1);
+        Point2D.Double dp4 = evalDt(t1);
+
+        Point2D.Double np3 = new Point2D.Double(np4.x-dt*dp4.x/3,
+                                                np4.y-dt*dp4.y/3);
+        return new Cubic(np1, np2, np3, np4);
+    }
+
+    private static int count = 0;
+
+    protected double subLength(double leftLegLen, double rightLegLen,
+                               double maxErr) {
+        count++;
+        double cldx, cldy, cdx, cdy;
+        cldx = p3.x-p2.x;
+        cldy = p3.y-p2.y;
+        double crossLegLen = Math.sqrt(cldx*cldx+cldy*cldy);
+
+        cdx = p4.x-p1.x;
+        cdy = p4.y-p1.y;
+        double cordLen = Math.sqrt(cdx*cdx+cdy*cdy);
+
+        double hullLen = leftLegLen+rightLegLen+crossLegLen;
+        if (hullLen < maxErr) return (hullLen+cordLen)/2;
+
+        double err = (hullLen-cordLen);
+        if (err < maxErr)
+            return (hullLen+cordLen)/2;
+
+        Cubic c  = new Cubic();
+        double npX = (p1.x+3*(p2.x+p3.x)+p4.x)*0.125;
+        double npY = (p1.y+3*(p2.y+p3.y)+p4.y)*0.125;
+
+        double npdx = (cldx + cdx)*.125;
+        double npdy = (cldy + cdy)*.125;
+
+        c.p1.x = p1.x;
+        c.p1.y = p1.y;
+        c.p2.x = (p2.x+p1.x)*.5;
+        c.p2.y = (p2.y+p1.y)*.5;
+
+        c.p3.x = npX-npdx;
+        c.p3.y = npY-npdy;
+        c.p4.x = npX;
+        c.p4.y = npY;
+
+        double midLen = Math.sqrt(npdx*npdx+npdy*npdy);
+        double len = c.subLength(leftLegLen/2, midLen, maxErr/2);
+
+        c.p1.x = npX;
+        c.p1.y = npY;
+        c.p2.x = npX+npdx;
+        c.p2.y = npY+npdy;
+
+        c.p3.x = (p4.x+p3.x)*.5;
+        c.p3.y = (p4.y+p3.y)*.5;
+        c.p4.x = p4.x;
+        c.p4.y = p4.y;
+
+        len += c.subLength(midLen, rightLegLen/2, maxErr/2);
+        return len;
+    }
+
+    public double getLength() {
+        return getLength(0.000001);
+    }
+
+    public double getLength(double maxErr) {
+        double dx, dy;
+        dx = p2.x-p1.x;
+        dy = p2.y-p1.y;
+        double leftLegLen = Math.sqrt(dx*dx+dy*dy);
+        dx = p4.x-p3.x;
+        dy = p4.y-p3.y;
+        double rightLegLen = Math.sqrt(dx*dx+dy*dy);
+        dx = p3.x-p2.x;
+        dy = p3.y-p2.y;
+        double crossLegLen = Math.sqrt(dx*dx+dy*dy);
+
+        double eps = maxErr*(leftLegLen+rightLegLen+crossLegLen);
+
+        return subLength(leftLegLen, rightLegLen, eps);
+    }
+
+    public String toString() {
+        return "M" + p1.x + ',' + p1.y +
+                'C' + p2.x + ',' + p2.y + ' ' +
+                p3.x + ',' + p3.y + ' ' +
+                p4.x + ',' + p4.y;
+    }
+    /*
+    public static  boolean epsEq(double a, double b) {
+        final double eps = 0.000001;
+        return (((a + eps) > b) && ((a-eps) < b));
+    }
+
+    public static void sub(Cubic orig, Cubic curr,
+                           double t, double inc, int lev) {
+        Cubic left=new Cubic();
+        Cubic right=new Cubic();
+        curr.subdivide(left, right);
+        Point2D.Double ptl = left.eval(.5);
+        Point2D.Double ptr = right.eval(.5);
+        Point2D.Double pt1  = orig.eval(t-inc);
+        Point2D.Double pt2  = orig.eval(t+inc);
+        int steps = 100;
+        Point2D.Double l, r, o;
+        for (int i=0; i<=steps; i++) {
+            l = left.eval(i/(double)steps);
+            o = orig.eval(t-(2*inc)*(1-i/(double)steps));
+            if (!epsEq(l.x, o.x) || !epsEq(l.y, o.y))
+                System.err.println("Lf Pt: ["  + l.x + "," + l.y +
+                                   "] Orig: [" + o.x + "," + o.y +"]");
+            r = right.eval(i/(double)steps);
+            o = orig.eval(t+(2*inc*i/(double)steps));
+            if (!epsEq(r.x, o.x) || !epsEq(r.y, o.y))
+                System.err.println("Rt Pt: ["  + r.x + "," + r.y +
+                                   "] Orig: [" + o.x + "," + o.y +"]");
+        }
+        if (lev != 0) {
+            sub(orig, left,  t-inc, inc/2, lev-1);
+            sub(orig, right, t+inc, inc/2, lev-1);
+        }
+    }
+
+    public static void evalCubic(Cubic c) {
+
+        int steps = 1000000;
+        Point2D.Double oldP = c.eval(0);
+        Point2D.Double  newP;
+        double len = 0;
+        for (int i=1; i<=steps; i++) {
+            newP = c.eval(i/(double)steps);
+            double dx = newP.x-oldP.x;
+            double dy = newP.y-oldP.y;
+            len += Math.sqrt(dx*dx + dy*dy);
+            oldP = newP;
+        }
+        System.err.println("Length(.1): " + c.getLength(.001) +
+                           " x " + count); count = 0;
+        System.err.println("Length    : " + c.getLength() +
+                           " x " + count); count = 0;
+        System.err.println("D  Len    : " + len);
+    }
+
+    public static void main(String args[]) {
+        Cubic c;
+
+        c = new Cubic(0,0,  10,10,  20,-10,  30,0);
+        sub(c, c, .5, .25, 3);
+        evalCubic(c);
+
+        c = new Cubic(0,0,  1,0,  2,-1,  3,0);
+        sub(c, c, .5, .25, 3);
+        evalCubic(c);
+    }
+    */
+}

Propchange: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/geom/Cubic.java
------------------------------------------------------------------------------
    svn:eol-style = native