incubator-flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cframp...@apache.org
Subject svn commit: r1402274 [3/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...
Date Thu, 25 Oct 2012 19:01:49 GMT
Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RadialGradientPaintContext.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RadialGradientPaintContext.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RadialGradientPaintContext.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RadialGradientPaintContext.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,784 @@
+/*
+
+   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;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+
+/**
+ * Provides the actual implementation for the RadialGradientPaint.
+ * This is where the pixel processing is done.  A RadialGradienPaint
+ * only supports circular gradients, but it should be possible to scale
+ * the circle to look approximately elliptical, by means of a
+ * gradient transform passed into the RadialGradientPaint constructor.
+ *
+ * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @version $Id: RadialGradientPaintContext.java 516969 2007-03-11 17:39:37Z dvholten $
+ *
+ */
+final class RadialGradientPaintContext extends MultipleGradientPaintContext {
+
+    /** True when (focus == center)  */
+    private boolean isSimpleFocus = false;
+
+    /** True when (cycleMethod == NO_CYCLE) */
+    private boolean isNonCyclic = false;
+
+    /** Radius of the outermost circle defining the 100% gradient stop. */
+    private float radius;
+
+    /** Variables representing center and focus points. */
+    private float centerX, centerY, focusX, focusY;
+
+    /** Radius of the gradient circle squared. */
+    private float radiusSq;
+
+    /** Constant part of X, Y user space coordinates. */
+    private float constA, constB;
+
+    /** This value represents the solution when focusX == X.  It is called
+     * trivial because it is easier to calculate than the general case.
+     */
+    private float trivial;
+
+    private static final int FIXED_POINT_IMPL = 1;
+    private static final int DEFAULT_IMPL     = 2;
+    private static final int ANTI_ALIAS_IMPL  = 3;
+
+    private int fillMethod;
+
+    /** Amount for offset when clamping focus. */
+    private static final float SCALEBACK = 0.999f;
+
+    /**
+     * Constructor for RadialGradientPaintContext.
+     *
+     *  @param cm {@link ColorModel} that receives
+     *  the <code>Paint</code> data. This is used only as a hint.
+     *
+     *  @param deviceBounds the device space bounding box of the
+     *  graphics primitive being rendered
+     *
+     *  @param userBounds the user space bounding box of the
+     *  graphics primitive being rendered
+     *
+     *  @param t the {@link AffineTransform} from user
+     *  space into device space (gradientTransform should be
+     *  concatenated with this)
+     *
+     *  @param hints the hints that the context object uses to choose
+     *  between rendering alternatives
+     *
+     *  @param cx the center point in user space of the circle defining
+     *  the gradient.  The last color of the gradient is mapped to the
+     *  perimeter of this circle X coordinate
+     *
+     *  @param cy the center point in user space of the circle defining
+     *  the gradient.  The last color of the gradient is mapped to the
+     *  perimeter of this circle Y coordinate
+     *
+     *  @param r the radius of the circle defining the extents of the
+     *  color gradient
+     *
+     *  @param fx the point in user space to which the first color is mapped
+     *  X coordinate
+     *
+     *  @param fy the point in user space to which the first color is mapped
+     *  Y coordinate
+     *
+     *  @param fractions the fractions specifying the gradient distribution
+     *
+     *  @param colors the gradient colors
+     *
+     *  @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
+     *
+     *  @param colorSpace which colorspace to use for interpolation,
+     *  either SRGB or LINEAR_RGB
+     *
+     */
+    public RadialGradientPaintContext(ColorModel cm,
+                                      Rectangle deviceBounds,
+                                      Rectangle2D userBounds,
+                                      AffineTransform t,
+                                      RenderingHints hints,
+                                      float cx, float cy,
+                                      float r,
+                                      float fx, float fy,
+                                      float[] fractions,
+                                      Color[] colors,
+                                      MultipleGradientPaint.CycleMethodEnum
+                                      cycleMethod,
+                                      MultipleGradientPaint.ColorSpaceEnum
+                                      colorSpace)
+        throws NoninvertibleTransformException
+    {
+        super(cm, deviceBounds, userBounds, t, hints, fractions, colors,
+              cycleMethod, colorSpace);
+
+        //copy some parameters.
+        centerX = cx;
+        centerY = cy;
+        focusX = fx;
+        focusY = fy;
+        radius = r;
+
+        this.isSimpleFocus = (focusX == centerX) && (focusY == centerY);
+        this.isNonCyclic = (cycleMethod == RadialGradientPaint.NO_CYCLE);
+
+        //for use in the quadractic equation
+        radiusSq = radius * radius;
+
+        float dX = focusX - centerX;
+        float dY = focusY - centerY;
+
+        double dist = Math.sqrt((dX * dX) + (dY * dY));
+
+        //test if distance from focus to center is greater than the radius
+        if (dist > radius* SCALEBACK) { //clamp focus to radius
+          double angle = Math.atan2(dY, dX);
+
+          //x = r cos theta, y = r sin theta
+          focusX = (float)(SCALEBACK * radius * Math.cos(angle)) + centerX;
+
+          focusY = (float)(SCALEBACK * radius * Math.sin(angle)) + centerY;
+        }
+
+        //calculate the solution to be used in the case where X == focusX
+        //in cyclicCircularGradientFillRaster
+        dX = focusX - centerX;
+        trivial = (float)Math.sqrt(radiusSq - (dX * dX));
+
+        // constant parts of X, Y user space coordinates
+        constA = a02 - centerX;
+        constB = a12 - centerY;
+
+        Object colorRend = hints.get(RenderingHints.KEY_COLOR_RENDERING);
+        Object rend      = hints.get(RenderingHints.KEY_RENDERING);
+
+        fillMethod = 0;
+
+        if ((rend      == RenderingHints.VALUE_RENDER_QUALITY) ||
+            (colorRend == RenderingHints.VALUE_COLOR_RENDER_QUALITY)) {
+            // System.out.println("AAHints set: " + rend + ", " + colorRend);
+            fillMethod = ANTI_ALIAS_IMPL;
+        }
+
+        if ((rend      == RenderingHints.VALUE_RENDER_SPEED) ||
+            (colorRend == RenderingHints.VALUE_COLOR_RENDER_SPEED)) {
+            // System.out.println("SPHints set: " + rend + ", " + colorRend);
+            fillMethod = DEFAULT_IMPL;
+        }
+
+        // We are in the 'default' case, no hint or hint set to
+        // DEFAULT values...
+        if (fillMethod == 0) {
+            // For now we will always use the 'default' impl if
+            // one is not specified.
+            fillMethod = DEFAULT_IMPL;
+
+            if (false) {
+                // This could be used for a 'smart' choice in
+                // the default case, if the gradient has obvious
+                // discontinuites use AA, otherwise default
+                if (hasDiscontinuity) {
+                    fillMethod = ANTI_ALIAS_IMPL;
+                } else {
+                    fillMethod = DEFAULT_IMPL;
+                }
+            }
+        }
+
+        if ((fillMethod == DEFAULT_IMPL) &&
+            (isSimpleFocus && isNonCyclic && isSimpleLookup)) {
+            this.calculateFixedPointSqrtLookupTable();
+            fillMethod = FIXED_POINT_IMPL;
+        }
+    }
+
+    /**
+     * Return a Raster containing the colors generated for the graphics
+     * operation.
+     *
+     * @param x The x coordinate of the area in device space for which colors
+     *          are generated.
+     * @param y The y coordinate of the area in device space for which colors
+     *          are generated.
+     * @param w The width of the area in device space for which colors
+     *          are generated.
+     * @param h The height of the area in device space for which colors
+     *          are generated.
+     */
+    protected void fillRaster(int[] pixels, int off, int adjust,
+                              int x, int y, int w, int h) {
+        switch(fillMethod) {
+        case FIXED_POINT_IMPL:
+            // System.out.println("Calling FP");
+            fixedPointSimplestCaseNonCyclicFillRaster(pixels, off, adjust, x,
+                                                      y, w, h);
+            break;
+        case ANTI_ALIAS_IMPL:
+            // System.out.println("Calling AA");
+            antiAliasFillRaster(pixels, off, adjust, x, y, w, h);
+            break;
+        case DEFAULT_IMPL:
+        default:
+            // System.out.println("Calling Default");
+            cyclicCircularGradientFillRaster(pixels, off, adjust, x, y, w, h);
+        }
+    }
+
+    /**
+     * This code works in the simplest of cases, where the focus == center
+     * point, the gradient is noncyclic, and the gradient lookup method is
+     * fast (single array index, no conversion necessary).
+     *
+     */
+    private void fixedPointSimplestCaseNonCyclicFillRaster(int[] pixels,
+                                                           int off,
+                                                           int adjust,
+                                                           int x, int y,
+                                                           int w, int h) {
+        float iSq=0;  // Square distance index
+        final float indexFactor = fastGradientArraySize / radius;
+
+        //constant part of X and Y coordinates for the entire raster
+        final float constX = (a00*x) + (a01*y) + constA;
+        final float constY = (a10*x) + (a11*y) + constB;
+        final float deltaX = indexFactor * a00; //incremental change in dX
+        final float deltaY = indexFactor * a10; //incremental change in dY
+        float dX, dY; //the current distance from center
+        final int fixedArraySizeSq=
+            (fastGradientArraySize * fastGradientArraySize);
+        float g, gDelta, gDeltaDelta, temp; //gradient square value
+        int gIndex; // integer number used to index gradient array
+        int iSqInt; // Square distance index
+
+        int end, j; //indexing variables
+        int indexer = off;//used to index pixels array
+
+        temp        = ((deltaX * deltaX) + (deltaY * deltaY));
+        gDeltaDelta = ((temp * 2));
+
+        if (temp > fixedArraySizeSq) {
+            // This combination of scale and circle radius means
+            // essentially no pixels will be anything but the end
+            // stop color.  This also avoids math problems.
+            final int val = gradientOverflow;
+            for(j = 0; j < h; j++){ //for every row
+                //for every column (inner loop begins here)
+                for (end = indexer+w; indexer < end; indexer++)
+                    pixels[indexer] = val;
+                indexer += adjust;
+            }
+            return;
+        }
+
+        // For every point in the raster, calculate the color at that point
+        for(j = 0; j < h; j++){ //for every row
+            //x and y (in user space) of the first pixel of this row
+            dX = indexFactor * ((a01*j) + constX);
+            dY = indexFactor * ((a11*j) + constY);
+
+            // these values below here allow for an incremental calculation
+            // of dX^2 + dY^2
+
+            //initialize to be equal to distance squared
+            g = (((dY * dY) + (dX * dX)) );
+            gDelta = (deltaY * dY + deltaX * dX) * 2 + temp;
+
+            //for every column (inner loop begins here)
+            for (end = indexer+w; indexer < end; indexer++) {
+                //determine the distance to the center
+
+                //since this is a non cyclic fill raster, crop at "1" and 0
+                if (g >= fixedArraySizeSq) {
+                    pixels[indexer] = gradientOverflow;
+                }
+
+                // This should not happen as gIndex is a square
+                // quantity. Code commented out on purpose, can't underflow.
+                // else if (g < 0) {
+                //    gIndex = 0;
+                // }
+
+                else {
+                    iSq = (g * invSqStepFloat);
+
+                    iSqInt = (int)iSq; //chop off fractional part
+                    iSq -= iSqInt;
+                    gIndex = sqrtLutFixed[iSqInt];
+                    gIndex += (int)(iSq * (sqrtLutFixed[iSqInt + 1]-gIndex));
+                    pixels[indexer] = gradient[gIndex];
+                }
+
+
+                //incremental calculation
+                g += gDelta;
+                gDelta += gDeltaDelta;
+            }
+            indexer += adjust;
+        }
+    }
+
+    /** Length of a square distance intervale in the lookup table */
+    private float invSqStepFloat;
+
+    /** Used to limit the size of the square root lookup table */
+    private static final int MAX_PRECISION = 256;
+
+    /** Square root lookup table */
+    private int[] sqrtLutFixed = new int[MAX_PRECISION];
+
+    /**
+     * Build square root lookup table
+     */
+    private void calculateFixedPointSqrtLookupTable() {
+        float sqStepFloat;
+        sqStepFloat = (fastGradientArraySize * fastGradientArraySize)
+                       / (MAX_PRECISION - 2.0f);
+
+        // The last two values are the same so that linear square root
+        // interpolation can happen on the maximum reachable element in the
+        // lookup table (precision-2)
+        int[] workTbl = sqrtLutFixed;      // local is cheaper
+        int i;
+        for (i = 0; i < MAX_PRECISION - 1; i++) {
+            workTbl[i] = (int)Math.sqrt(i*sqStepFloat);
+        }
+        workTbl[i] = workTbl[i-1];
+        invSqStepFloat = 1.0f/sqStepFloat;
+    }
+
+    /** Fill the raster, cycling the gradient colors when a point falls outside
+     *  of the perimeter of the 100% stop circle.
+     *
+     *  This calculation first computes the intersection point of the line
+     *  from the focus through the current point in the raster, and the
+     *  perimeter of the gradient circle.
+     *
+     *  Then it determines the percentage distance of the current point along
+     *  that line (focus is 0%, perimeter is 100%).
+     *
+     *  Equation of a circle centered at (a,b) with radius r:
+     *  (x-a)^2 + (y-b)^2 = r^2
+     *  Equation of a line with slope m and y-intercept b
+     *  y = mx + b
+     *  replacing y in the cirlce equation and solving using the quadratic
+     *  formula produces the following set of equations.  Constant factors have
+     *  been extracted out of the inner loop.
+     *
+     */
+    private void cyclicCircularGradientFillRaster(int[] pixels, int off,
+                                                  int adjust,
+                                                  int x, int y,
+                                                  int w, int h) {
+        // Constant part of the C factor of the quadratic equation
+        final double constC =
+            -(radiusSq) + (centerX * centerX) + (centerY * centerY);
+        double A; //coefficient of the quadratic equation (Ax^2 + Bx + C = 0)
+        double B; //coefficient of the quadratic equation
+        double C; //coefficient of the quadratic equation
+        double slope; //slope of the focus-perimeter line
+        double yintcpt; //y-intercept of the focus-perimeter line
+        double solutionX;//intersection with circle X coordinate
+        double solutionY;//intersection with circle Y coordinate
+               final float constX = (a00*x) + (a01*y) + a02;//const part of X coord
+        final float constY = (a10*x) + (a11*y) + a12; //const part of Y coord
+               final float precalc2 = 2 * centerY;//const in inner loop quad. formula
+        final float precalc3 =-2 * centerX;//const in inner loop quad. formula
+        float X; // User space point X coordinate
+        float Y; // User space point Y coordinate
+        float g;//value between 0 and 1 specifying position in the gradient
+        float det; //determinant of quadratic formula (should always be >0)
+        float currentToFocusSq;//sq distance from the current pt. to focus
+        float intersectToFocusSq;//sq distance from the intersect pt. to focus
+        float deltaXSq; //temp variable for a change in X squared.
+        float deltaYSq; //temp variable for a change in Y squared.
+        int indexer = off; //index variable for pixels array
+        int i, j; //indexing variables for FOR loops
+        int pixInc = w+adjust;//incremental index change for pixels array
+
+        for (j = 0; j < h; j++) { //for every row
+
+            X = (a01*j) + constX; //constants from column to column
+            Y = (a11*j) + constY;
+
+            //for every column (inner loop begins here)
+            for (i = 0; i < w; i++) {
+
+                // special case to avoid divide by zero or very near zero
+                if (((X-focusX)>-0.000001f) &&
+                    ((X-focusX)< 0.000001f)) {
+                    solutionX = focusX;
+
+                    solutionY = centerY;
+
+                    solutionY += (Y > focusY)?trivial:-trivial;
+                }
+
+                else {
+
+                    //slope of the focus-current line
+                    slope =   (Y - focusY) / (X - focusX);
+
+                    yintcpt = Y - (slope * X); //y-intercept of that same line
+
+                    //use the quadratic formula to calculate the intersection
+                    //point
+                    A = (slope * slope) + 1;
+
+                    B =  precalc3 + (-2 * slope * (centerY - yintcpt));
+
+                    C =  constC + (yintcpt* (yintcpt - precalc2));
+
+                    det = (float)Math.sqrt((B * B) - ( 4 * A * C));
+
+                    solutionX = -B;
+
+                    //choose the positive or negative root depending
+                    //on where the X coord lies with respect to the focus.
+                    solutionX += (X < focusX)?-det:det;
+
+                    solutionX = solutionX / (2 * A);//divisor
+
+                    solutionY = (slope * solutionX) + yintcpt;
+                }
+
+                //calculate the square of the distance from the current point
+                //to the focus and the square of the distance from the
+                //intersection point to the focus. Want the squares so we can
+                //do 1 square root after division instead of 2 before.
+
+                deltaXSq = (float)solutionX - focusX;
+                deltaXSq = deltaXSq * deltaXSq;
+
+                deltaYSq = (float)solutionY - focusY;
+                deltaYSq = deltaYSq * deltaYSq;
+
+                intersectToFocusSq = deltaXSq + deltaYSq;
+
+                deltaXSq = X - focusX;
+                deltaXSq = deltaXSq * deltaXSq;
+
+                deltaYSq = Y - focusY;
+                deltaYSq = deltaYSq * deltaYSq;
+
+                currentToFocusSq = deltaXSq + deltaYSq;
+
+                //want the percentage (0-1) of the current point along the
+                //focus-circumference line
+                g = (float)Math.sqrt(currentToFocusSq / intersectToFocusSq);
+
+                //Get the color at this point
+                pixels[indexer + i] = indexIntoGradientsArrays(g);
+
+                X += a00; //incremental change in X, Y
+                Y += a10;
+            } //end inner loop
+            indexer += pixInc;
+        } //end outer loop
+    }
+
+
+    /** Fill the raster, cycling the gradient colors when a point
+     *  falls outside of the perimeter of the 100% stop circle. Use
+     *  the anti-aliased gradient lookup.
+     *
+     *  This calculation first computes the intersection point of the line
+     *  from the focus through the current point in the raster, and the
+     *  perimeter of the gradient circle.
+     *
+     *  Then it determines the percentage distance of the current point along
+     *  that line (focus is 0%, perimeter is 100%).
+     *
+     *  Equation of a circle centered at (a,b) with radius r:
+     *  (x-a)^2 + (y-b)^2 = r^2
+     *  Equation of a line with slope m and y-intercept b
+     *  y = mx + b
+     *  replacing y in the cirlce equation and solving using the quadratic
+     *  formula produces the following set of equations.  Constant factors have
+     *  been extracted out of the inner loop.
+     * */
+    private void antiAliasFillRaster(int[] pixels, int off,
+                                     int adjust,
+                                     int x, int y,
+                                     int w, int h) {
+        // Constant part of the C factor of the quadratic equation
+        final double constC =
+            -(radiusSq) + (centerX * centerX) + (centerY * centerY);
+        //coefficients of the quadratic equation (Ax^2 + Bx + C = 0)
+               final float precalc2 = 2 * centerY;//const in inner loop quad. formula
+        final float precalc3 =-2 * centerX;//const in inner loop quad. formula
+
+        //const part of X,Y coord (shifted to bottom left corner of pixel.
+               final float constX = (a00*(x-.5f)) + (a01*(y+.5f)) + a02;
+        final float constY = (a10*(x-.5f)) + (a11*(y+.5f)) + a12;
+        float X; // User space point X coordinate
+        float Y; // User space point Y coordinate
+        int i, j; //indexing variables for FOR loops
+        int indexer = off-1; //index variable for pixels array
+
+        double [] prevGs = new double[w+1];
+        double deltaXSq, deltaYSq;
+        double solutionX, solutionY;
+        double slope, yintcpt, A, B, C, det;
+        double intersectToFocusSq, currentToFocusSq;
+        double g00, g01, g10, g11;
+
+        // Set X,Y to top left corner of first pixel of first row.
+        X = constX - a01;
+        Y = constY - a11;
+
+        // Calc top row of g's.
+        for (i=0; i <= w; i++) {
+            final float dx = X - focusX;
+
+            // special case to avoid divide by zero or very near zero
+            if ( ( dx >-0.000001f ) &&
+                 ( dx < 0.000001f ))  {
+                solutionX = focusX;
+                solutionY = centerY;
+                solutionY += (Y > focusY)?trivial:-trivial;
+            }
+            else {
+                // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
+                // Formula line:        Y = Slope*x + Y0;
+                //
+                // So you substitue line into Circle and apply
+                // Quadradic formula.
+
+
+                //slope of the focus-current line
+                slope =   (Y - focusY) / (X - focusX);
+
+                yintcpt = Y - (slope * X); //y-intercept of that same line
+
+                //use the quadratic formula to calculate the intersection
+                //point
+                A = (slope * slope) + 1;
+
+                B =  precalc3 + (-2 * slope * (centerY - yintcpt));
+
+                C =  constC + (yintcpt* (yintcpt - precalc2));
+
+                det = Math.sqrt((B * B) - ( 4 * A * C));
+
+                solutionX = -B;
+
+                //choose the positive or negative root depending
+                //on where the X coord lies with respect to the focus.
+                solutionX += (X < focusX)?-det:det;
+
+                solutionX = solutionX / (2 * A);//divisor
+
+                solutionY = (slope * solutionX) + yintcpt;
+            }
+
+            //calculate the square of the distance from the current point
+            //to the focus and the square of the distance from the
+            //intersection point to the focus. Want the squares so we can
+            //do 1 square root after division instead of 2 before.
+            deltaXSq = solutionX - focusX;
+            deltaXSq = deltaXSq * deltaXSq;
+
+            deltaYSq = solutionY - focusY;
+            deltaYSq = deltaYSq * deltaYSq;
+
+            intersectToFocusSq = deltaXSq + deltaYSq;
+
+            deltaXSq = X - focusX;
+            deltaXSq = deltaXSq * deltaXSq;
+
+            deltaYSq = Y - focusY;
+            deltaYSq = deltaYSq * deltaYSq;
+
+            currentToFocusSq = deltaXSq + deltaYSq;
+
+            //want the percentage (0-1) of the current point along the
+            //focus-circumference line
+            prevGs[i] = Math.sqrt(currentToFocusSq / intersectToFocusSq);
+
+            X += a00; //incremental change in X, Y
+            Y += a10;
+        }
+
+        for (j = 0; j < h; j++) { //for every row
+
+            // Set X,Y to bottom edge of pixel row.
+            X = (a01*j) + constX; //constants from row to row
+            Y = (a11*j) + constY;
+
+            g10 = prevGs[0];
+
+            float dx = X - focusX;
+            // special case to avoid divide by zero or very near zero
+            if ( ( dx >-0.000001f ) &&
+                 ( dx < 0.000001f ))  {
+                solutionX = focusX;
+                solutionY = centerY;
+                solutionY += (Y > focusY)?trivial:-trivial;
+            }
+            else {
+                // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
+                // Formula line:        Y = Slope*x + Y0;
+                //
+                // So you substitue line into Circle and apply
+                // Quadradic formula.
+
+
+                //slope of the focus-current line
+                slope =   (Y - focusY) / (X - focusX);
+
+                yintcpt = Y - (slope * X); //y-intercept of that same line
+
+                //use the quadratic formula to calculate the intersection
+                //point
+                A = (slope * slope) + 1;
+
+                B =  precalc3 + (-2 * slope * (centerY - yintcpt));
+
+                C =  constC + (yintcpt* (yintcpt - precalc2));
+
+                det = Math.sqrt((B * B) - ( 4 * A * C));
+
+                solutionX = -B;
+
+                //choose the positive or negative root depending
+                //on where the X coord lies with respect to the focus.
+                solutionX += (X < focusX)?-det:det;
+
+                solutionX = solutionX / (2 * A);//divisor
+
+                solutionY = (slope * solutionX) + yintcpt;
+            }
+
+            //calculate the square of the distance from the current point
+            //to the focus and the square of the distance from the
+            //intersection point to the focus. Want the squares so we can
+            //do 1 square root after division instead of 2 before.
+            deltaXSq = solutionX - focusX;
+            deltaXSq = deltaXSq * deltaXSq;
+
+            deltaYSq = solutionY - focusY;
+            deltaYSq = deltaYSq * deltaYSq;
+
+            intersectToFocusSq = deltaXSq + deltaYSq;
+
+            deltaXSq = X - focusX;
+            deltaXSq = deltaXSq * deltaXSq;
+
+            deltaYSq = Y - focusY;
+            deltaYSq = deltaYSq * deltaYSq;
+
+            currentToFocusSq = deltaXSq + deltaYSq;
+            g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
+            prevGs[0] = g11;
+
+            X += a00; //incremental change in X, Y
+            Y += a10;
+
+            //for every column (inner loop begins here)
+            for (i=1; i <= w; i++) {
+                g00 = g10;
+                g01 = g11;
+                g10 = prevGs[i];
+
+                dx = X - focusX;
+                // special case to avoid divide by zero or very near zero
+                if ( ( dx >-0.000001f ) &&
+                     ( dx < 0.000001f ))  {
+                    solutionX = focusX;
+                    solutionY = centerY;
+                    solutionY += (Y > focusY)?trivial:-trivial;
+                }
+                else {
+                    // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
+                    // Formula line:        Y = Slope*x + Y0;
+                    //
+                    // So you substitue line into Circle and apply
+                    // Quadradic formula.
+
+
+                    //slope of the focus-current line
+                    slope =   (Y - focusY) / (X - focusX);
+
+                    yintcpt = Y - (slope * X); //y-intercept of that same line
+
+                    //use the quadratic formula to calculate the intersection
+                    //point
+                    A = (slope * slope) + 1;
+
+                    B =  precalc3 + (-2 * slope * (centerY - yintcpt));
+
+                    C =  constC + (yintcpt* (yintcpt - precalc2));
+
+                    det = Math.sqrt((B * B) - ( 4 * A * C));
+
+                    solutionX = -B;
+
+                    //choose the positive or negative root depending
+                    //on where the X coord lies with respect to the focus.
+                    solutionX += (X < focusX)?-det:det;
+
+                    solutionX = solutionX / (2 * A);//divisor
+
+                    solutionY = (slope * solutionX) + yintcpt;
+                }
+
+                //calculate the square of the distance from the current point
+                //to the focus and the square of the distance from the
+                //intersection point to the focus. Want the squares so we can
+                //do 1 square root after division instead of 2 before.
+                deltaXSq = solutionX - focusX;
+                deltaXSq = deltaXSq * deltaXSq;
+
+                deltaYSq = solutionY - focusY;
+                deltaYSq = deltaYSq * deltaYSq;
+
+                intersectToFocusSq = deltaXSq + deltaYSq;
+
+                deltaXSq = X - focusX;
+                deltaXSq = deltaXSq * deltaXSq;
+
+                deltaYSq = Y - focusY;
+                deltaYSq = deltaYSq * deltaYSq;
+
+                currentToFocusSq = deltaXSq + deltaYSq;
+                g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
+                prevGs[i] = g11;
+
+                //Get the color at this point
+                pixels[indexer+i] = indexGradientAntiAlias
+                    ((float)((g00+g01+g10+g11)/4),
+                     (float)Math.max(Math.abs(g11-g00),
+                                     Math.abs(g10-g01)));
+
+                X += a00; //incremental change in X, Y
+                Y += a10;
+            } //end inner loop
+            indexer += (w+adjust);
+        } //end outer loop
+    }
+}

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

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RenderingHintsKeyExt.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RenderingHintsKeyExt.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RenderingHintsKeyExt.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/RenderingHintsKeyExt.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,116 @@
+/*
+
+   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;
+
+import java.awt.RenderingHints;
+
+/**
+ * Contains additional RenderingHints Keys, such as
+ * KEY_AREA_OF_INTEREST
+ *
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @version $Id: RenderingHintsKeyExt.java 489226 2006-12-21 00:05:36Z cam $
+ */
+public final class RenderingHintsKeyExt {
+
+    public static final int KEY_BASE;
+
+    /**
+     * Hint as to the transcoding destination.
+     */
+    public static final RenderingHints.Key KEY_TRANSCODING;
+
+    public static final String VALUE_TRANSCODING_PRINTING = "Printing";
+
+    public static final String VALUE_TRANSCODING_VECTOR = "Vector";
+
+    /**
+     * Key for the AOI hint. This hint is used to propagate the AOI to Paint
+     * and PaintContext instances.
+     */
+    public static final RenderingHints.Key KEY_AREA_OF_INTEREST;
+
+    /**
+     * Hint for the destination of the rendering when it is a BufferedImage
+     * This works around the fact that Java 2D sometimes lies about the
+     * attributes of the Graphics2D device, when it is an image.
+     *
+     * It is strongly suggested that you use
+     * org.apache.flex.forks.batik.ext.awt.image.GraphicsUtil.createGraphics to
+     * create a Graphics2D from a BufferedImage, this will ensure that
+     * the proper things are done in the processes of creating the
+     * Graphics.  */
+    public static final RenderingHints.Key KEY_BUFFERED_IMAGE;
+
+    /**
+     * Hint to source that we only want an alpha channel.
+     * The source should follow the SVG spec for how to
+     * convert ARGB, RGB, Grey and AGrey to just an Alpha channel.
+     */
+    public static final RenderingHints.Key KEY_COLORSPACE;
+
+    /**
+     * Hint for the org.apache.flex.forks.batik.ext.awt.image.GraphicsUtil class that
+     * tiling of a bitmap during rendering is undesired. This is primarily
+     * for the PDF and PostScript transcoders where tiling can lead to
+     * suboptimal results due to overlaps in transparency and filter effects.
+     */
+    public static final RenderingHints.Key KEY_AVOID_TILE_PAINTING;
+
+    public static final Object VALUE_AVOID_TILE_PAINTING_ON = new Object();
+    public static final Object VALUE_AVOID_TILE_PAINTING_OFF = new Object();
+    public static final Object VALUE_AVOID_TILE_PAINTING_DEFAULT = new Object();
+
+    static {
+        int base = 10100;
+        RenderingHints.Key trans=null, aoi=null, bi=null, cs=null, atp=null;
+        while (true) {
+            int val = base;
+
+            try {
+                trans = new TranscodingHintKey   (val++);
+                aoi   = new AreaOfInterestHintKey(val++);
+                bi    = new BufferedImageHintKey (val++);
+                cs    = new ColorSpaceHintKey    (val++);
+                atp   = new AvoidTilingHintKey   (val++);
+            } catch (Exception e) {
+                System.err.println
+                    ("You have loaded the Batik jar files more than once\n" +
+                     "in the same JVM this is likely a problem with the\n" +
+                     "way you are loading the Batik jar files.");
+
+                base = (int)(Math.random()*2000000);
+                continue;
+            }
+            break;
+        }
+        KEY_BASE                = base;
+        KEY_TRANSCODING         = trans;
+        KEY_AREA_OF_INTEREST    = aoi;
+        KEY_BUFFERED_IMAGE      = bi;
+        KEY_COLORSPACE          = cs;
+        KEY_AVOID_TILE_PAINTING = atp;
+    }
+
+    /**
+     * Do not authorize creation of instances of that class
+     */
+    private RenderingHintsKeyExt(){
+    }
+}

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

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/TranscodingHintKey.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/TranscodingHintKey.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/TranscodingHintKey.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/TranscodingHintKey.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,42 @@
+/*
+
+   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;
+
+import java.awt.RenderingHints;
+
+/**
+ * TranscodingHint as to what the destination of the drawing is.
+ *
+ * @author <a href="mailto:deweese@apache.org">Thomas DeWeese</a>
+ * @version $Id: TranscodingHintKey.java 475477 2006-11-15 22:44:28Z cam $
+ */
+final class TranscodingHintKey extends RenderingHints.Key {
+
+    TranscodingHintKey(int number) { super(number); }
+
+    public boolean isCompatibleValue(Object val) {
+        boolean isCompatible = true;
+        if ((val != null) && !(val instanceof String)) {
+            isCompatible = false;
+        }
+        return isCompatible;
+    }
+}
+

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

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/ICCColorSpaceExt.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/ICCColorSpaceExt.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/ICCColorSpaceExt.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/ICCColorSpaceExt.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,121 @@
+/*
+
+   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.color;
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ICC_Profile;
+
+/**
+ * This class extends the ICCColorSpace class by providing
+ * convenience methods to convert to sRGB using various
+ * methods, forcing a givent intent, such as perceptual or
+ * relative colorimetric.
+ *
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @version $Id: ICCColorSpaceExt.java 504084 2007-02-06 11:24:46Z dvholten $
+ */
+public class ICCColorSpaceExt extends ICC_ColorSpace {
+    public static final int PERCEPTUAL = 0;
+    public static final int RELATIVE_COLORIMETRIC = 1;
+    public static final int ABSOLUTE_COLORIMETRIC = 2;
+    public static final int SATURATION = 3;
+    public static final int AUTO = 4;
+
+    static final ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+    int intent;
+
+    public ICCColorSpaceExt(ICC_Profile p, int intent){
+        super(p);
+
+        this.intent = intent;
+        switch(intent){
+        case AUTO:
+        case RELATIVE_COLORIMETRIC:
+        case ABSOLUTE_COLORIMETRIC:
+        case SATURATION:
+        case PERCEPTUAL:
+            break;
+        default:
+            throw new IllegalArgumentException();
+        }
+
+        /**
+         * Apply the requested intent into the profile
+         */
+        if(intent != AUTO){
+            byte[] hdr = p.getData(ICC_Profile.icSigHead);
+            hdr[ICC_Profile.icHdrRenderingIntent] = (byte)intent;
+        }
+    }
+
+    /**
+     * Returns the sRGB value obtained by forcing the
+     * conversion method to the intent passed to the
+     * constructor
+     */
+    public float[] intendedToRGB(float[] values){
+        switch(intent){
+            case ABSOLUTE_COLORIMETRIC:
+            return absoluteColorimetricToRGB(values);
+            case PERCEPTUAL:
+            case AUTO:
+            return perceptualToRGB(values);
+            case RELATIVE_COLORIMETRIC:
+            return relativeColorimetricToRGB(values);
+            case SATURATION:
+            return saturationToRGB(values);
+            default:
+            throw new Error("invalid intent:" + intent );
+        }
+    }
+
+    /**
+     * Perceptual conversion is the method implemented by the
+     * base class's toRGB method
+     */
+    public float[] perceptualToRGB(float[] values){
+        return toRGB(values);
+    }
+
+    /**
+     * Relative colorimetric needs to happen through CIEXYZ
+     * conversion
+     */
+    public float[] relativeColorimetricToRGB(float[] values){
+        float[] ciexyz = toCIEXYZ(values);
+        return sRGB.fromCIEXYZ(ciexyz);
+    }
+
+    /**
+     * Absolute colorimetric. NOT IMPLEMENTED.
+     * Temporarily returns same as perceptual
+     */
+    public float[] absoluteColorimetricToRGB(float[] values){
+        return perceptualToRGB(values);
+    }
+
+    /**
+     * Saturation. NOT IMPLEMENTED. Temporarily returns same
+     * as perceptual.
+     */
+    public float[] saturationToRGB(float[] values){
+        return perceptualToRGB(values);
+    }
+}

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

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/NamedProfileCache.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/NamedProfileCache.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/NamedProfileCache.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/color/NamedProfileCache.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,91 @@
+/*
+
+   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.color;
+
+import org.apache.flex.forks.batik.util.SoftReferenceCache;
+
+/**
+ * This class manages a cache of soft references to named profiles that
+ * we have already loaded. 
+ *
+ * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
+ * @version $Id: NamedProfileCache.java 475477 2006-11-15 22:44:28Z cam $
+ */
+public class NamedProfileCache extends SoftReferenceCache {
+
+    static NamedProfileCache theCache = new NamedProfileCache();
+
+    public static NamedProfileCache getDefaultCache() { return theCache; }
+
+    /**
+     * Let people create there own caches.
+     */
+    public NamedProfileCache() { }
+
+    /**
+     * Check if <tt>request(profileName)</tt> will return with a ICCColorSpaceExt
+     * (not putting you on the hook for it).  Note that it is possible
+     * that this will return true but between this call and the call
+     * to request the soft-reference will be cleared.  So it
+     * is still possible for request to return NULL, just much less
+     * likely (you can always call 'clear' in that case). 
+     */
+    public synchronized boolean isPresent(String profileName) {
+        return super.isPresentImpl(profileName);
+    }
+
+    /**
+     * Check if <tt>request(profileName)</tt> will return immediately with the
+     * ICCColorSpaceExt.  Note that it is possible that this will return
+     * true but between this call and the call to request the
+     * soft-reference will be cleared.
+     */
+    public synchronized boolean isDone(String profileName) {
+        return super.isDoneImpl(profileName);
+    }
+
+    /**
+     * If this returns null then you are now 'on the hook'.
+     * to put the ICCColorSpaceExt associated with String into the
+     * cache.  */
+    public synchronized ICCColorSpaceExt request(String profileName) {
+        return (ICCColorSpaceExt)super.requestImpl(profileName);
+    }
+
+    /**
+     * Clear the entry for String.
+     * This is the easiest way to 'get off the hook'.
+     * if you didn't indend to get on it.
+     */
+    public synchronized void clear(String profileName) {
+        super.clearImpl(profileName);
+    }
+
+    /**
+     * Associate bi with profileName.  bi is only referenced through
+     * a soft reference so don't rely on the cache to keep it
+     * around.  If the map no longer contains our profileName it was
+     * probably cleared or flushed since we were put on the hook
+     * for it, so in that case we will do nothing.
+     */
+    public synchronized void put(String profileName, ICCColorSpaceExt bi) {
+        super.putImpl(profileName, bi);
+    }
+}

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

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/TextPathLayout.java
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/TextPathLayout.java?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/TextPathLayout.java (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/TextPathLayout.java Thu Oct 25 19:01:43 2012
@@ -0,0 +1,249 @@
+/*
+
+   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.font;
+
+import java.awt.Shape;
+import java.awt.font.GlyphMetrics;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+
+import org.apache.flex.forks.batik.ext.awt.geom.PathLength;
+
+/**
+ * PathLayout can layout text along a Shape, usually a Path object.
+ * <p>
+ * There are a number of improvements that could be made to this class.
+ * I'll try to list some of them:
+ * <ul>
+ * <li> The layout should really only modify the GlyphVector, rather
+ *      than converting to a Shape.
+ * <li> Maybe the functions should take a AttributedCharacterIterator
+ *      or something? Should this class do the entire layout?
+ * <li> The layout code works, but it's definitely not perfect.
+ * </ul>
+ * @author <a href="mailto:dean.jackson@cmis.csiro.au">Dean Jackson</a>
+ * @version $Id: TextPathLayout.java 522271 2007-03-25 14:42:45Z dvholten $
+ */
+
+public class TextPathLayout {
+
+    /**
+     * Align the text at the start of the path.
+     */
+    public static final int ALIGN_START = 0;
+    /**
+     * Align the text at the middle of the path.
+     */
+    public static final int ALIGN_MIDDLE = 1;
+    /**
+     * Align the text at the end of the path.
+     */
+    public static final int ALIGN_END = 2;
+
+    /**
+     * Use the spacing between the glyphs to adjust for textLength.
+     */
+    public static final int ADJUST_SPACING = 0;
+    /**
+     * Use the entire glyph to adjust for textLength.
+     */
+    public static final int ADJUST_GLYPHS = 1;
+
+    /**
+     * Wraps the GlyphVector around the given path. The results
+     * are mostly quite nice but you need to be careful choosing
+     * the size of the font that created the GlyphVector, as
+     * well as the "curvyness" of the path (really dynamic curves
+     * don't look so great, abrupt changes/vertices look worse).
+     *
+     * @param glyphs The GlyphVector to layout.
+     * @param path The path (or shape) to wrap around
+     * @param align The text alignment to use. Should be one
+     *              of ALIGN_START, ALIGN_MIDDLE or ALIGN_END.
+     * @param startOffset The offset from the start of the path for the initial
+     *              text position.
+     * @param textLength The length that the text should fill.
+     * @param lengthAdjustMode The method used to expand or contract
+     *                         the text to meet the textLength.
+     * @return A shape that is the outline of the glyph vector
+     * wrapped along the path
+     */
+
+
+    public static Shape layoutGlyphVector(GlyphVector glyphs,
+                                          Shape path, int align,
+                                          float startOffset,
+                                          float textLength,
+                                          int lengthAdjustMode) {
+
+        GeneralPath newPath = new GeneralPath();
+        PathLength pl = new PathLength(path);
+        float pathLength = pl.lengthOfPath();
+
+        if ( glyphs == null ){
+            return newPath;
+        }
+        float glyphsLength = (float) glyphs.getVisualBounds().getWidth();
+
+        // return from the ugly cases
+        if (path == null ||
+            glyphs.getNumGlyphs() == 0 ||
+            pl.lengthOfPath() == 0f ||
+            glyphsLength == 0f) {
+            return newPath;
+        }
+
+        // work out the expansion/contraction per character
+        float lengthRatio = textLength / glyphsLength;
+
+        // the current start point of the character on the path
+        float currentPosition = startOffset;
+
+        // if align is START then a currentPosition of 0f
+        // is correct.
+        // if align is END then the currentPosition should
+        // be enough to place the last character on the end
+        // of the path
+        // if align is MIDDLE then the currentPosition should
+        // be enough to center the glyphs on the path
+
+        if (align == ALIGN_END) {
+            currentPosition += pathLength - textLength;
+        } else if (align == ALIGN_MIDDLE) {
+            currentPosition += (pathLength - textLength) / 2;
+        }
+
+        // iterate through the GlyphVector placing each glyph
+
+        for (int i = 0; i < glyphs.getNumGlyphs(); i++) {
+
+            GlyphMetrics gm = glyphs.getGlyphMetrics(i);
+
+            float charAdvance = gm.getAdvance();
+
+            Shape glyph = glyphs.getGlyphOutline(i);
+
+            // if lengthAdjust was GLYPHS, then scale the glyph
+            // by the lengthRatio in the X direction
+            // FIXME: for vertical text this will be the Y direction
+            if (lengthAdjustMode == ADJUST_GLYPHS) {
+                AffineTransform scale = AffineTransform.getScaleInstance(lengthRatio, 1.0f);
+                glyph = scale.createTransformedShape(glyph);
+
+                // charAdvance has to scale accordingly
+                charAdvance *= lengthRatio;
+            }
+
+            float glyphWidth = (float) glyph.getBounds2D().getWidth();
+
+            // Use either of these to calculate the mid point
+            // of the character along the path.
+            // If you change this, you must also change the
+            // transform on the glyph down below
+            // In some case this gives better layout, but
+            // the way it is at the moment is a closer match
+            // to the textPath layout from the SVG spec
+
+            //float charMidPos = currentPosition + charAdvance / 2f;
+            float charMidPos = currentPosition + glyphWidth / 2f;
+
+            // Calculate the actual point to place the glyph around
+            Point2D charMidPoint = pl.pointAtLength(charMidPos);
+
+            // Check if the glyph is actually on the path
+
+            if (charMidPoint != null) {
+
+                // Calculate the normal to the path (midline of glyph)
+                float angle = pl.angleAtLength(charMidPos);
+
+                // Define the transform of the glyph
+                AffineTransform glyphTrans = new AffineTransform();
+
+                // translate to the point on the path
+                glyphTrans.translate(charMidPoint.getX(), charMidPoint.getY());
+
+                // rotate midline of glyph to be normal to path
+                glyphTrans.rotate(angle);
+
+                // translate glyph backwards so we rotate about the
+                // center of the glyph
+                // Choose one of these translations - see the comments
+                // in the charMidPos calculation above
+                glyphTrans.translate(charAdvance / -2f, 0f);
+                //glyphTrans.translate(glyphWidth / -2f, 0f);
+
+                glyph = glyphTrans.createTransformedShape(glyph);
+                newPath.append(glyph, false);
+
+            }
+
+            // move along by the advance value
+            // if the lengthAdjustMode was SPACING then
+            // we have to take this into account here
+            if (lengthAdjustMode == ADJUST_SPACING) {
+                currentPosition += (charAdvance * lengthRatio);
+            } else {
+                currentPosition += charAdvance;
+            }
+
+        }
+
+        return newPath;
+    }
+
+    /**
+     * Wraps the GlyphVector around the given path.
+     *
+     * @param glyphs The GlyphVector to layout.
+     * @param path The path (or shape) to wrap around
+     * @param align The text alignment to use. Should be one
+     *              of ALIGN_START, ALIGN_MIDDLE or ALIGN_END.
+     * @return A shape that is the outline of the glyph vector
+     * wrapped along the path
+     */
+
+    public static Shape layoutGlyphVector(GlyphVector glyphs,
+                                          Shape path, int align) {
+
+        return layoutGlyphVector(glyphs, path, align, 0f,
+                                 (float) glyphs.getVisualBounds().getWidth(),
+                                 ADJUST_SPACING);
+    }
+
+    /**
+     * Wraps the GlyphVector around the given path.
+     *
+     * @param glyphs The GlyphVector to layout.
+     * @param path The path (or shape) to wrap around
+     * @return A shape that is the outline of the glyph vector
+     * wrapped along the path
+     */
+
+    public static Shape layoutGlyphVector(GlyphVector glyphs,
+                                          Shape path) {
+
+        return layoutGlyphVector(glyphs, path, ALIGN_START);
+    }
+
+
+} // TextPathLayout

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

Added: incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/package.html
URL: http://svn.apache.org/viewvc/incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/package.html?rev=1402274&view=auto
==============================================================================
--- incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/package.html (added)
+++ incubator/flex/sdk/branches/develop/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/ext/awt/font/package.html Thu Oct 25 19:01:43 2012
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+  <head>
+    <title>org.apache.batik.ext.awt.font</title>
+  </head>
+
+  <body>
+Contains extensions to the <tt>java.awt.font</tt> package. This
+package provides new <tt>TextLayout</tt> algorithm and a comprehensive
+way to handle SVG text attributes such stroked text or multiple font families.
+  </body>
+</html>

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



Mime
View raw message