You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by de...@apache.org on 2001/07/11 14:24:02 UTC

cvs commit: xml-batik/samples/tests radialGradient2.svg

deweese     01/07/11 05:24:02

  Modified:    sources/org/apache/batik/bridge
                        AbstractSVGGradientElementBridge.java
               sources/org/apache/batik/ext/awt
                        MultipleGradientPaintContext.java
                        RadialGradientPaintContext.java
               sources/org/apache/batik/util ParsedURL.java
                        ParsedURLData.java
  Added:       samples/tests radialGradient2.svg
  Log:
  1) Removed use of java.net.URL.getPath (JDK 1.3ism).
  
  2) Fixed handling of stops that use the same offset value.
  3) Added test file for #1 (also test complex lookup gradient code).
  4) Added anti-aliased implementation of gradient lookup code.
     The use of anti-aliasing is currently controlled by the
     private final static USE_ANTI_ALIAS in RadialGradientPaintContext.
     Compare radialGradient2 with and without anti-aliasing :)
  
  PR: 1563
  
  Revision  Changes    Path
  1.2       +3 -5      xml-batik/sources/org/apache/batik/bridge/AbstractSVGGradientElementBridge.java
  
  Index: AbstractSVGGradientElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/AbstractSVGGradientElementBridge.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractSVGGradientElementBridge.java	2001/05/02 14:33:32	1.1
  +++ AbstractSVGGradientElementBridge.java	2001/07/11 12:23:55	1.2
  @@ -29,7 +29,7 @@
    * Bridge class for vending gradients.
    *
    * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
  - * @version $Id: AbstractSVGGradientElementBridge.java,v 1.1 2001/05/02 14:33:32 tkormann Exp $
  + * @version $Id: AbstractSVGGradientElementBridge.java,v 1.2 2001/07/11 12:23:55 deweese Exp $
    */
   public abstract class AbstractSVGGradientElementBridge extends AbstractSVGBridge
       implements PaintBridge, ErrorConstants {
  @@ -233,10 +233,8 @@
                   stops = new LinkedList();
               }
               if (previous != null) {
  -                if (stop.offset == previous.offset) {
  -                    stops.removeLast();
  -                } else if (stop.offset < previous.offset) {
  -                    stop.offset = previous.offset+0.01f;
  +                if (stop.offset < previous.offset) {
  +                    stop.offset = previous.offset;
                   }
               }
               stops.add(stop);
  
  
  
  1.7       +518 -1    xml-batik/sources/org/apache/batik/ext/awt/MultipleGradientPaintContext.java
  
  Index: MultipleGradientPaintContext.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/MultipleGradientPaintContext.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- MultipleGradientPaintContext.java	2001/04/30 22:01:00	1.6
  +++ MultipleGradientPaintContext.java	2001/07/11 12:23:57	1.7
  @@ -23,11 +23,13 @@
    *
    * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: MultipleGradientPaintContext.java,v 1.6 2001/04/30 22:01:00 deweese Exp $
  + * @version $Id: MultipleGradientPaintContext.java,v 1.7 2001/07/11 12:23:57 deweese Exp $
    *
    */
   abstract class MultipleGradientPaintContext implements PaintContext {
   
  +    protected final static boolean DEBUG = false;
  +
       /**
        * The color model data is generated in (always un premult).
        */
  @@ -104,6 +106,12 @@
        */
       protected int[][] gradients;
   
  +    /** This holds the blend of all colors in the gradient.
  +     *  we use this at extreamly low resolutions to ensure we
  +     *  get a decent blend of the colors.
  +     */
  +    protected int gradientAverage;
  +
       /** Length of the 2D slow lookup gradients array. */
       protected int gradientsLength;
   
  @@ -412,6 +420,12 @@
   
           int gradientsTot = 1; //the eventual size of the single array
   
  +        // These are fixed point 8.16 (start with 0.5)
  +        int aveA = 0x008000;
  +        int aveR = 0x008000;
  +        int aveG = 0x008000;
  +        int aveB = 0x008000;
  +
           //for every interval (transition between 2 colors)
           for(int i=0; i < gradients.length; i++){
   
  @@ -428,11 +442,24 @@
               //fill this array with the colors in between rgb1 and rgb2
               interpolate(rgb1, rgb2, gradients[i]);
   
  +            // Calculate Average of two colors...
  +            int argb = gradients[i][GRADIENT_SIZE/2];
  +            float norm = normalizedIntervals[i];
  +            aveA += (int)(((argb>> 8)&0xFF0000)*norm);
  +            aveR += (int)(((argb    )&0xFF0000)*norm);
  +            aveG += (int)(((argb<< 8)&0xFF0000)*norm);
  +            aveB += (int)(((argb<<16)&0xFF0000)*norm);
  +
               //if the colors are opaque, transparency should still be 0xff000000
               transparencyTest &= rgb1;
               transparencyTest &= rgb2;
           }
   
  +        gradientAverage = (((aveA & 0xFF0000)<< 8) |
  +                           ((aveR & 0xFF0000)    ) |
  +                           ((aveG & 0xFF0000)>> 8) |
  +                           ((aveB & 0xFF0000)>>16));
  +
           // Put all gradients in a single array
           gradient = new int[gradientsTot];
           int curOffset = 0;
  @@ -494,6 +521,12 @@
           int rgb1; //2 colors to interpolate
           int rgb2;
   
  +        // These are fixed point 8.16 (start with 0.5)
  +        int aveA = 0x008000;
  +        int aveR = 0x008000;
  +        int aveG = 0x008000;
  +        int aveB = 0x008000;
  +
           //for every interval (transition between 2 colors)
           for(int i=0; i < gradients.length; i++){
   
  @@ -507,11 +540,24 @@
               //fill this array with the colors in between rgb1 and rgb2
               interpolate(rgb1, rgb2, gradients[i]);
   
  +            // Calculate Average of two colors...
  +            int argb = gradients[i][GRADIENT_SIZE/2];
  +            float norm = normalizedIntervals[i];
  +            aveA += (int)(((argb>> 8)&0xFF0000)*norm);
  +            aveR += (int)(((argb    )&0xFF0000)*norm);
  +            aveG += (int)(((argb<< 8)&0xFF0000)*norm);
  +            aveB += (int)(((argb<<16)&0xFF0000)*norm);
  +
               //if the colors are opaque, transparency should still be 0xff000000
               transparencyTest &= rgb1;
               transparencyTest &= rgb2;
           }
   
  +        gradientAverage = (((aveA & 0xFF0000)<< 8) |
  +                           ((aveR & 0xFF0000)    ) |
  +                           ((aveG & 0xFF0000)>> 8) |
  +                           ((aveB & 0xFF0000)>>16));
  +
           //if interpolation occurred in Linear RGB space, convert the
           //gradients back to SRGB using the lookup table
           if (colorSpace == LinearGradientPaint.LINEAR_RGB) {
  @@ -761,6 +807,477 @@
   
           return gradients[gradients.length - 1][GRADIENT_SIZE_INDEX];
       }
  +
  +
  +    /** Helper function to index into the gradients array.  This is necessary
  +     * because each interval has an array of colors with uniform size 255.
  +     * However, the color intervals are not necessarily of uniform length, so
  +     * a conversion is required.  This version also does anti-aliasing by
  +     * averaging the gradient over position+/-(sz/2).
  +     *
  +     * @param position the unmanipulated position.  want to map this into the
  +     * range 0 to 1
  +     * @param sz the size in gradient space to average.
  +     *
  +     * @returns ARGB integer color to display
  +     */
  +    protected final int indexGradientAntiAlias(float position, float sz) {
  +
  +        //first, manipulate position value depending on the cycle method.
  +        if (cycleMethod == MultipleGradientPaint.NO_CYCLE) {
  +            if (DEBUG) System.out.println("NO_CYCLE");
  +            float p1 = position-(sz/2);
  +            float p2 = position+(sz/2);
  +
  +            if (p1 > 1) {
  +                if (isSimpleLookup)
  +                    return gradient[fastGradientArraySize];
  +                else 
  +                    return gradients[gradients.length-1][GRADIENT_SIZE_INDEX];
  +            }
  +            if (p2 < 0) {
  +                if (isSimpleLookup) return gradient[0];
  +                else                return gradients[0][0];
  +            }
  +            int interior;
  +            float top_weight=0, bottom_weight=0, frac;
  +            if (p2 > 1) {
  +                top_weight = (p2-1)/sz;
  +                if (p1 <0) {
  +                    bottom_weight = -p1/sz;
  +                    frac=1;
  +                    interior = gradientAverage;
  +                } else {
  +                    frac=1-p1;
  +                    interior = getAntiAlias(p1, true, 1, false, 1-p1, 1);
  +                }
  +            } else if (p1 < 0) {
  +                bottom_weight = -p1/sz;
  +                frac = p2;
  +                interior = getAntiAlias(0, true, p2, false, p2, 1);
  +            } else
  +                return getAntiAlias(p1, true, p2, false, sz, 1);
  +            
  +            int norm = (int)((1<<16)*frac/sz);
  +            int pA = (((interior>>>20)&0xFF0)*norm)>>16;
  +            int pR = (((interior>> 12)&0xFF0)*norm)>>16;
  +            int pG = (((interior>>  4)&0xFF0)*norm)>>16;
  +            int pB = (((interior<<  4)&0xFF0)*norm)>>16;
  +
  +            if (bottom_weight != 0) {
  +                int bPix;
  +                if (isSimpleLookup) bPix = gradient[0];
  +                else                bPix = gradients[0][0];
  +
  +                // System.out.println("ave: " + gradientAverage);
  +                norm = (int)((1<<16)*bottom_weight);
  +                pA += (((bPix>>>20) & 0xFF0)*norm)>>16;
  +                pR += (((bPix>> 12) & 0xFF0)*norm)>>16;
  +                pG += (((bPix>>  4) & 0xFF0)*norm)>>16;
  +                pB += (((bPix<<  4) & 0xFF0)*norm)>>16;
  +            }
  +
  +            if (top_weight != 0) {
  +                int tPix;
  +                if (isSimpleLookup)
  +                    tPix = gradient[fastGradientArraySize];
  +                else 
  +                    tPix = gradients[gradients.length-1][GRADIENT_SIZE_INDEX];
  +
  +                norm = (int)((1<<16)*top_weight);
  +                pA += (((tPix>>>20) & 0xFF0)*norm)>>16;
  +                pR += (((tPix>> 12) & 0xFF0)*norm)>>16;
  +                pG += (((tPix>>  4) & 0xFF0)*norm)>>16;
  +                pB += (((tPix<<  4) & 0xFF0)*norm)>>16;
  +            }
  +
  +            return (((pA&0xFF0)<<20)  |
  +                    ((pR&0xFF0)<<12)  |
  +                    ((pG&0xFF0)<< 4)  |
  +                    ((pB&0xFF0)>> 4));
  +        }
  +
  +        // See how many times we are going to "wrap around" the gradient,
  +        // array.
  +        int intSz = (int)sz;
  +        
  +        float weight = 1f;
  +        if (intSz != 0) {
  +            // We need to make sure that sz is < 1.0 otherwise 
  +            // p1 and p2 my pass each other which will cause no end of
  +            // trouble.
  +            sz -= intSz;
  +            weight = (1-sz)/(intSz+sz);
  +            if (weight < 0.1)
  +                // The part of the color from the location will be swamped
  +                // by the averaged part of the gradient so just use the
  +                // average color for the gradient.
  +                return gradientAverage;
  +        }
  +            
  +        // So close to full gradient just use the average value...
  +        if (sz > 0.99)
  +            return gradientAverage;
  +            
  +            // Go up and down from position by 1/2 sz.
  +        float p1 = position-(sz/2);
  +        float p2 = position+(sz/2);
  +        if (DEBUG) System.out.println("P1: " + p1 + " P2: " + p2);
  +
  +        // These indicate the direction to go from p1 and p2 when
  +        // averaging...
  +        boolean p1_up=true;
  +        boolean p2_up=false;
  +
  +        if (cycleMethod == MultipleGradientPaint.REPEAT) {
  +            if (DEBUG) System.out.println("REPEAT");
  +
  +            // Get positions between -1 and 1
  +            p1=p1-(int)p1;
  +            p2=p2-(int)p2;
  +
  +            // force to be in rage 0-1.
  +            if (p1 <0) p1 += 1;
  +            if (p2 <0) p2 += 1;
  +        }
  +
  +        else {  //cycleMethod == MultipleGradientPaint.REFLECT
  +            if (DEBUG) System.out.println("REFLECT");
  +
  +            //take absolute values
  +            // Note when we reflect we change sense of p1/2_up.
  +            if (p2 < 0) {
  +                p1 = -p1; p1_up = !p1_up;
  +                p2 = -p2; p2_up = !p2_up;
  +            } else if (p1 < 0) { 
  +                p1 = -p1; p1_up = !p1_up; 
  +            }
  +
  +            int part1, part2;
  +            part1 = (int)p1;   // take the integer part
  +            p1   = p1 - part1; // get the fractional part
  +
  +            part2 = (int)p2;   // take the integer part
  +            p2   = p2 - part2; // get the fractional part
  +
  +            // if integer part is odd we want the reflected color instead.
  +            // Note when we reflect we change sense of p1/2_up.
  +            if ((part1 & 0x01) == 1) {
  +                p1 = 1-p1;
  +                p1_up = !p1_up;
  +            }
  +
  +            if ((part2 & 0x01) == 1) {
  +                p2 = 1-p2;
  +                p2_up = !p2_up;
  +            }
  +
  +            // Check if in the end they just got switched around.
  +            // this commonly happens if they both end up negative.
  +            if ((p1 > p2) && !p1_up && p2_up) {
  +                float t = p1;
  +                p1 = p2; 
  +                p2 = t;
  +                p1_up = true;
  +                p2_up = false;
  +            }
  +        }
  +
  +        return getAntiAlias(p1, p1_up, p2, p2_up, sz, weight);
  +    }
  +
  +
  +    private final int getAntiAlias(float p1, boolean p1_up,
  +                                   float p2, boolean p2_up,
  +                                   float sz, float weight) {
  +
  +        // Until the last set of ops these are 28.4 fixed point values.
  +        int ach=0, rch=0, gch=0, bch=0;
  +        if (isSimpleLookup) {
  +            p1 *= fastGradientArraySize;
  +            p2 *= fastGradientArraySize;
  +
  +            int idx1 = (int)p1;
  +            int idx2 = (int)p2;
  +
  +            // Simpliest case we just take the average value.
  +            // Note that this may not be correct in all cases,
  +            // but saves us always doing the summation between idx1 and idx2.
  +            if ((idx1 <= idx2) && p1_up && !p2_up)
  +                return gradient[(idx1+idx2)>>1];
  +
  +            if (DEBUG) System.out.println( "P1: " + p1 + " " + p1_up +
  +                                           " P2: " + p2 + " " + p2_up);
  +
  +            // Do the bulk of the work, all the whole gradient entries
  +            // for idx1 and idx2.
  +            int pix, norm;
  +            if (p1_up) {
  +                for (int i=idx1+1; i<fastGradientArraySize; i++) {
  +                    pix  = gradient[i];
  +                    ach += ((pix>>>20)&0xFF0);
  +                    rch += ((pix>>>12)&0xFF0);
  +                    gch += ((pix>>> 4)&0xFF0);
  +                    bch += ((pix<<  4)&0xFF0);
  +                }
  +            } else {
  +                for (int i=0; i<idx1; i++) {
  +                    pix  = gradient[i];
  +                    ach += ((pix>>>20)&0xFF0);
  +                    rch += ((pix>>>12)&0xFF0);
  +                    gch += ((pix>>> 4)&0xFF0);
  +                    bch += ((pix<<  4)&0xFF0);
  +                }
  +            }
  +
  +            if (p2_up) {
  +                for (int i=idx2+1; i<fastGradientArraySize; i++) {
  +                    pix  = gradient[i];
  +                    ach += ((pix>>>20)&0xFF0);
  +                    rch += ((pix>>>12)&0xFF0);
  +                    gch += ((pix>>> 4)&0xFF0);
  +                    bch += ((pix<<  4)&0xFF0);
  +                }
  +            } else {
  +                for (int i=0; i<idx2; i++) {
  +                    pix  = gradient[i];
  +                    ach += ((pix>>>20)&0xFF0);
  +                    rch += ((pix>>>12)&0xFF0);
  +                    gch += ((pix>>> 4)&0xFF0);
  +                    bch += ((pix<<  4)&0xFF0);
  +                }
  +            }
  +
  +            // Normalize the summation so far...
  +            int isz = (int)((1<<16)/(sz*fastGradientArraySize));
  +            ach = (ach*isz)>>16;
  +            rch = (rch*isz)>>16;
  +            gch = (gch*isz)>>16;
  +            bch = (bch*isz)>>16;
  +
  +            // Clean up with the partial buckets at each end.
  +            if (p1_up) norm = (int)(((1-(p1-idx1))*(1<<16))
  +                                    /(sz*fastGradientArraySize));
  +            else       norm = (int)(((p1-idx1)*(1<<16))
  +                                    /(sz*fastGradientArraySize));
  +            pix = gradient[idx1];
  +            ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +            rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +            gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +            bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +
  +            if (p2_up) norm = (int)(((1-(p2-idx2))*(1<<16))
  +                                    /(sz*fastGradientArraySize));
  +            else       norm = (int)(((p2-idx2)*(1<<16))
  +                                    /(sz*fastGradientArraySize));
  +            pix = gradient[idx2];
  +            ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +            rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +            gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +            bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +
  +            // Round and drop the 4bits frac.
  +            ach = (ach+0x08)>>4;
  +            rch = (rch+0x08)>>4;
  +            gch = (gch+0x08)>>4;
  +            bch = (bch+0x08)>>4;
  +
  +        } else {
  +            int idx1=0, idx2=0;
  +            int i1=-1, i2=-1;
  +            float f1=0, f2=0;
  +            // Find which gradient interval our points fall into.
  +            for (int i = 0; i < gradientsLength; i++) {
  +                if ((p1 < fractions[i+1]) && (i1 == -1)) { 
  +                    //this is the array we want
  +                    i1 = i;
  +                    f1 = p1 - fractions[i];
  +
  +                    f1 = ((f1/normalizedIntervals[i])
  +                             *GRADIENT_SIZE_INDEX);
  +                    //this is the  interval we want.
  +                    idx1 = (int)f1;
  +                    if (i2 != -1) break;
  +                }
  +                if ((p2 < fractions[i+1]) && (i2 == -1)) { 
  +                    //this is the array we want
  +                    i2 = i;
  +                    f2 = p2 - fractions[i];
  +                    
  +                    f2 = ((f2/normalizedIntervals[i])
  +                             *GRADIENT_SIZE_INDEX);
  +                    //this is the interval we want.
  +                    idx2 = (int)f2;
  +                    if (i1 != -1) break;
  +                }
  +            }
  +
  +            if (i1 == -1) {
  +                i1 = gradients.length - 1;
  +                f1 = idx1 = GRADIENT_SIZE_INDEX;
  +            }
  +
  +            if (i2 == -1) {
  +                i2 = gradients.length - 1;
  +                f2 = idx2 = GRADIENT_SIZE_INDEX;
  +            }
  +
  +            if (DEBUG) System.out.println("I1: " + i1 + " Idx1: " + idx1 +
  +                                          " I2: " + i2 + " Idx2: " + idx2); 
  +
  +            // Simple case within one gradient array (so the average
  +            // of the two idx gives us the true average of colors).
  +            if ((i1 == i2) && (idx1 <= idx2) && p1_up && !p2_up)
  +                return gradients[i1][(idx1+idx2+1)>>1];
  +
  +            // i1 != i2
  +
  +            int pix, norm;
  +            int base = (int)((1<<16)/sz);
  +            if ((i1 < i2) && p1_up && !p2_up) {
  +                norm = (int)((base
  +                              *normalizedIntervals[i1]
  +                              *(GRADIENT_SIZE_INDEX-f1))
  +                             /GRADIENT_SIZE_INDEX);
  +                pix  = gradients[i1][(idx1+GRADIENT_SIZE)>>1];
  +                ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +
  +                for (int i=i1+1; i<i2; i++) {
  +                    norm = (int)(base*normalizedIntervals[i]);
  +                    pix  = gradients[i][GRADIENT_SIZE>>1];
  +                  
  +                    ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                    rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                    gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                    bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +                }
  +
  +                norm = (int)((base*normalizedIntervals[i2]*f2)
  +                             /GRADIENT_SIZE_INDEX);
  +                pix  = gradients[i2][(idx2+1)>>1];
  +                ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +            } else {
  +                if (p1_up) {
  +                    norm = (int)((base
  +                                  *normalizedIntervals[i1]
  +                                  *(GRADIENT_SIZE_INDEX-f1))
  +                                 /GRADIENT_SIZE_INDEX);
  +                    pix  = gradients[i1][(idx1+GRADIENT_SIZE)>>1];
  +                } else {
  +                    norm = (int)((base*normalizedIntervals[i1]*f1)
  +                                 /GRADIENT_SIZE_INDEX);
  +                    pix  = gradients[i1][(idx1+1)>>1];
  +                }
  +                ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +
  +                if (p2_up) {
  +                    norm = (int)((base
  +                                  *normalizedIntervals[i2]
  +                                  *(GRADIENT_SIZE_INDEX-f2))
  +                                 /GRADIENT_SIZE_INDEX);
  +                    pix  =  gradients[i2][(idx2+GRADIENT_SIZE)>>1];
  +                } else {
  +                    norm = (int)((base*normalizedIntervals[i2]*f2)
  +                                 /GRADIENT_SIZE_INDEX);
  +                    pix  = gradients[i2][(idx2+1)>>1];
  +                }
  +                ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +
  +                if (p1_up) {
  +                    for (int i=i1+1; i<gradientsLength; i++) {
  +                        norm = (int)(base*normalizedIntervals[i]);
  +                        pix  = gradients[i][GRADIENT_SIZE>>1];
  +
  +                        ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                        rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                        gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                        bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +                    }
  +                } else {
  +                    for (int i=0; i<i1; i++) {
  +                        norm = (int)(base*normalizedIntervals[i]);
  +                        pix  = gradients[i][GRADIENT_SIZE>>1];
  +                  
  +                        ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                        rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                        gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                        bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +                    }
  +                }
  +
  +                if (p2_up) {
  +                    for (int i=i2+1; i<gradientsLength; i++) {
  +                        norm = (int)(base*normalizedIntervals[i]);
  +                        pix  = gradients[i][GRADIENT_SIZE>>1];
  +
  +                        ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                        rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                        gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                        bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +                    }
  +                } else {
  +                    for (int i=0; i<i2; i++) {
  +                        norm = (int)(base*normalizedIntervals[i]);
  +                        pix  = gradients[i][GRADIENT_SIZE>>1];
  +
  +                        ach += (((pix>>>20)&0xFF0) *norm)>>16;
  +                        rch += (((pix>>>12)&0xFF0) *norm)>>16;
  +                        gch += (((pix>>> 4)&0xFF0) *norm)>>16;
  +                        bch += (((pix<<  4)&0xFF0) *norm)>>16;
  +                    }
  +                }
  +
  +            }
  +            ach = (ach+0x08)>>4;
  +            rch = (rch+0x08)>>4;
  +            gch = (gch+0x08)>>4;
  +            bch = (bch+0x08)>>4;
  +            if (DEBUG) System.out.println("Pix: [" + ach + ", " + rch + 
  +                                          ", " + gch + ", " + bch + "]");
  +        }
  +
  +        if (weight != 1) {
  +            // System.out.println("ave: " + gradientAverage);
  +            int aveW = (int)((1<<16)*(1-weight));
  +            int aveA = ((gradientAverage>>>24) & 0xFF)*aveW;
  +            int aveR = ((gradientAverage>> 16) & 0xFF)*aveW;
  +            int aveG = ((gradientAverage>>  8) & 0xFF)*aveW;
  +            int aveB = ((gradientAverage     ) & 0xFF)*aveW;
  +
  +            int iw = (int)(weight*(1<<16));
  +            ach = ((ach*iw)+aveA)>>16;
  +            rch = ((rch*iw)+aveR)>>16;
  +            gch = ((gch*iw)+aveG)>>16;
  +            bch = ((bch*iw)+aveB)>>16;
  +        }
  +        // If any high bits are set we are not in range.
  +              // If the highest bit is set then we are negative so
  +              // clamp to zero else we are > 255 so clamp to 255.
  +        if ((ach & 0xFFFFFF00) != 0)
  +            ach = ((ach & 0x80000000) != 0)?0:255;
  +        if ((rch & 0xFFFFFF00) != 0)
  +            rch = ((rch & 0x80000000) != 0)?0:255;
  +        if ((gch & 0xFFFFFF00) != 0)
  +            gch = ((gch & 0x80000000) != 0)?0:255;
  +        if ((bch & 0xFFFFFF00) != 0)
  +            bch = ((bch & 0x80000000) != 0)?0:255;
  +
  +              
  +        return ((ach<<24) | (rch<<16) | (gch<<8) | bch);
  +    }
  +
   
       /** Helper function to convert a color component in sRGB space to linear
        * RGB space.  Used to build a static lookup table.
  
  
  
  1.4       +22 -12    xml-batik/sources/org/apache/batik/ext/awt/RadialGradientPaintContext.java
  
  Index: RadialGradientPaintContext.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/RadialGradientPaintContext.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- RadialGradientPaintContext.java	2001/04/27 19:53:40	1.3
  +++ RadialGradientPaintContext.java	2001/07/11 12:23:58	1.4
  @@ -21,11 +21,13 @@
    *
    * @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,v 1.3 2001/04/27 19:53:40 deweese Exp $
  + * @version $Id: RadialGradientPaintContext.java,v 1.4 2001/07/11 12:23:58 deweese Exp $
    *
    */
   final class RadialGradientPaintContext extends MultipleGradientPaintContext {  
       
  +    private static final boolean USE_ANTI_ALIAS = false;
  +
       /** True when (focus == center)  */
       private boolean isSimpleFocus = false;
   
  @@ -418,6 +420,8 @@
           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
  +
  +        float delta, pixSzSq = (float)(a00*a00+a01*a01+a10*a10+a11*a11);
   	
           for (j = 0; j < h; j++) { //for every row
   	    
  @@ -427,8 +431,9 @@
               //for every column (inner loop begins here)
               for (i = 0; i < w; i++) {	       			
   	
  -                // special case to avoid divide by zero
  -                if (X == focusX) {		   
  +                // special case to avoid divide by zero or very near zero
  +                if (((X-focusX)>-0.000001) &&
  +                    ((X-focusX)< 0.000001)) {		   
                       solutionX = focusX;
   		    
                       solutionY = centerY;
  @@ -469,28 +474,33 @@
                   //intersection point to the focus. Want the squares so we can
                   //do 1 square root after division instead of 2 before.
   
  -                deltaXSq = X - focusX;
  +                deltaXSq = (float)solutionX - focusX;
                   deltaXSq = deltaXSq * deltaXSq;
   
  -                deltaYSq = Y - focusY;
  +                deltaYSq = (float)solutionY - focusY;
                   deltaYSq = deltaYSq * deltaYSq;
   
  -                currentToFocusSq = deltaXSq + deltaYSq;
  +                intersectToFocusSq = deltaXSq + deltaYSq;
   
  -                deltaXSq = (float)solutionX - focusX;
  +                deltaXSq = X - focusX;
                   deltaXSq = deltaXSq * deltaXSq;
   
  -                deltaYSq = (float)solutionY - focusY;
  +                deltaYSq = Y - focusY;
                   deltaYSq = deltaYSq * deltaYSq;
   
  -                intersectToFocusSq = deltaXSq + deltaYSq;
  +                currentToFocusSq = deltaXSq + deltaYSq;
   
                   //want the percentage (0-1) of the current point along the 
                   //focus-circumference line
                   g = (float)Math.sqrt(currentToFocusSq / intersectToFocusSq);
  -	       	       		
  -                //save the color at this point
  -                pixels[indexer + i] = indexIntoGradientsArrays(g);
  +
  +                //Get the color at this point
  +                if (USE_ANTI_ALIAS) {
  +                    delta = (float)Math.sqrt(pixSzSq/intersectToFocusSq);
  +                    pixels[indexer + i] = indexGradientAntiAlias(g, delta);
  +                } else {
  +                    pixels[indexer + i] = indexIntoGradientsArrays(g);
  +                }
   		
                   X += a00; //incremental change in X, Y
                   Y += a10;	
  
  
  
  1.6       +3 -1      xml-batik/sources/org/apache/batik/util/ParsedURL.java
  
  Index: ParsedURL.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/util/ParsedURL.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ParsedURL.java	2001/05/03 22:11:04	1.5
  +++ ParsedURL.java	2001/07/11 12:23:59	1.6
  @@ -259,7 +259,9 @@
   
       /**
        * Returns the path for this URL, if any (where appropriate for
  -     * the protocol this also includes the file, not just directory.) 
  +     * the protocol this also includes the file, not just directory).
  +     * Note that getPath appears in JDK 1.3 as a synonym for getFile
  +     * from JDK 1.2.
        */
       public String getPath()     { 
           if (data.path == null) return null;
  
  
  
  1.2       +1 -1      xml-batik/sources/org/apache/batik/util/ParsedURLData.java
  
  Index: ParsedURLData.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/util/ParsedURLData.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ParsedURLData.java	2001/05/03 22:11:05	1.1
  +++ ParsedURLData.java	2001/07/11 12:24:00	1.2
  @@ -83,7 +83,7 @@
   
           port     = url.getPort();
   
  -        path     = url.getPath();
  +        path     = url.getFile();
           if ((path != null) && (path.length() == 0)) 
               path = null;
   
  
  
  
  1.1                  xml-batik/samples/tests/radialGradient2.svg
  
  Index: radialGradient2.svg
  ===================================================================
  <?xml version="1.0" standalone="no"?>
  <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20000802//EN"
  "http://www.w3.org/TR/2000/CR-SVG-20000802/DTD/svg-20000802.dtd">
  
  <!-- ========================================================================= -->
  <!-- Copyright (C) The Apache Software Foundation. All rights reserved.        -->
  <!--                                                                           -->
  <!-- This software is published under the terms of the Apache Software License -->
  <!-- version 1.1, a copy of which has been included with this distribution in  -->
  <!-- the LICENSE file.                                                         -->
  <!-- ========================================================================= -->
  
  <!-- ========================================================================= -->
  <!-- @author vhardy@apache.org                                                 -->
  <!-- @version $Id: radialGradient2.svg,v 1.1 2001/07/11 12:24:01 deweese Exp $ -->
  <!-- ========================================================================= -->
  <?xml-stylesheet type="text/css" href="test.css" ?>  
  
  <svg id="body" width="450" height="500" viewBox="0 0 450 500">
  <title>&lt;radialGradient&gt; Test A</title>
  
  
      <text class="title" x="50%" y="40">&lt;radialGradient&gt; Test</text>
  
      <defs>
          <!-- Shape filled by radial gradients -->
          <g id="testShape">
              <rect x="-25" y="-20" width="50" height="40" />
          </g>
  
          <!-- ========================================== -->
          <!-- Two gradients, one with no values defined  -->
          <!-- and one with the default values specified  -->
          <!-- They should create the same pattern        -->
          <!-- ========================================== -->
          <radialGradient id="rgDefaults">
              <stop offset=".0" stop-color="gold" />
              <stop offset=".5" stop-color="crimson" />
              <stop offset=".5" stop-color="gold" />
              <stop offset="1." stop-color="crimson" />
          </radialGradient>
  
          <radialGradient id="rgSpecifiedDefaults" 
                          gradientUnits="objectBoundingBox"
                          cx="50%" cy="50%"
                          r="50%"
                          fx="50%" fy="50%"
                          spreadMethod="pad" xlink:href="#rgDefaults" />
  
          <!-- ========================================== -->
          <!-- gradientUnits. The following gradients     -->
          <!-- is defined so as to produce the same       -->
          <!-- result as with the default settings        -->
          <!-- For example, cx default is 50% in object   -->
          <!-- bounding box, which is .5*50 = 25          -->
          <!-- r = sqrt(50*50 + 40*40) = 22.63846284534354156643452041746 -->
          <!-- ========================================== -->
          <radialGradient id="rgUserSpaceOnUse" 
              cx="0" cy="0" r="22.63846284534354156643452041746"
              fx="0" fy="0" xlink:href="#rdDefaults" />
  
          <radialGradient id="rgCxCyA" xlink:href="#rgDefaults"
              cx="0%" cy="100%">
          </radialGradient>
  
          <radialGradient id="rgCxCyB" xlink:href="#rgDefaults"
              cx="75%" cy="25%">
          </radialGradient>
  
          <radialGradient id="rgFxFyA" xlink:href="#rgCxCyA"
              fx="0%" fy="100%">
          </radialGradient>
  
          <radialGradient id="rgFxFyB" xlink:href="#rgDefaults"
              fx="60%" fy="40%">
          </radialGradient>
  
          <radialGradient id="rgFxFyC" xlink:href="#rgDefaults"
              fx="0%" fy="50%">
          </radialGradient>
  
          <radialGradient id="rgFxFyD" xlink:href="#rgDefaults"
              fx="0%" fy="0%">
          </radialGradient>
  
          <radialGradient id="rgSpreadA" xlink:href="#rgDefaults"
              r=".125">
          </radialGradient>
  
          <radialGradient id="rgSpreadB" xlink:href="#rgDefaults"
              r=".125" spreadMethod="reflect">
          </radialGradient>
  
          <radialGradient id="rgSpreadC" xlink:href="#rgDefaults"
              r=".125" spreadMethod="repeat">
          </radialGradient>
  
          <radialGradient id="rgTxfA" xlink:href="#rgDefaults"
              gradientTransform="translate(.5, .5)" />
  
          <radialGradient id="rgTxfB" xlink:href="#rgDefaults"
              cx="0%" cy="0%" gradientTransform="translate(.5, .5)" />
  
          <radialGradient id="rgTxfC" xlink:href="#rgDefaults"
              cx="0%" cy="0%" gradientTransform="translate(.5, .5) scale(.25, 1.5)" />
  
          <radialGradient id="rgTxfD" xlink:href="#rgFxFyD"
              gradientTransform="scale(.5, .5)" />
  
      </defs>
  
      <g class="legend">
   
          <g transform="translate(70, 0)">
  
          <g transform="translate(0, 100)">
              <use xlink:href="#testShape" fill="url(#rgDefaults)" />
              <text y="-30">Defaults</text>
          </g>
  
          <g transform="translate(0, 170)">
              <use xlink:href="#testShape" fill="url(#rgSpecifiedDefaults)" />
              <text y="-30">Forced Defaults</text>
          </g>
  
          <g transform="translate(0, 240)">
              <use xlink:href="#testShape" fill="url(#rgSpecifiedDefaults)" />
              <text y="-30">userSpaceOnUse</text>
          </g>
  
          <g transform="translate(0, 310)">
              <use xlink:href="#testShape" fill="url(#rgCxCyA)" />
              <text y="-30">(cx,cy) = (0%, 100%)</text>
          </g>
  
          <g transform="translate(0, 380)">
              <use xlink:href="#testShape" fill="url(#rgCxCyB)" />
              <text y="-30">(cx,cy) = (75%, 25%)</text>
          </g>
  
          </g>
  
          <g transform="translate(200, 0)">
  
          <g transform="translate(0, 100)">
              <use xlink:href="#testShape" fill="url(#rgFxFyB)" />
              <text y="-30">(fx,fy)=(60%,40%)</text>
          </g>
  
          <g transform="translate(0, 170)">
              <use xlink:href="#testShape" fill="url(#rgFxFyC)" />
              <text y="-30">(fx,fy)=(0%,50%)</text>
          </g>
  
          <g transform="translate(0, 240)">
              <use xlink:href="#testShape" fill="url(#rgFxFyD)" />
              <text y="-30">(fx,fy)=(0%,0%)</text>
          </g>
  
          <g transform="translate(0, 310)">
              <use xlink:href="#testShape" fill="url(#rgSpreadA)" />
              <text y="-30">r=.125, spread=default</text>
          </g>
  
          <g transform="translate(0, 380)">
              <use xlink:href="#testShape" fill="url(#rgSpreadB)" />
              <text y="-30">r=.125, spread=reflect</text>
          </g>
  
          <g transform="translate(0, 450)">
              <use xlink:href="#testShape" fill="url(#rgSpreadC)" />
              <text y="-30">r=.125, spread=repeat</text>
          </g>
  
          </g>
  
  
          <g transform="translate(330, 0)">
  
          <g transform="translate(0, 100)">
              <use xlink:href="#testShape" fill="url(#rgTxfA)" />
              <text y="-30">translate(.5,.5)</text>
          </g>
  
          <g transform="translate(0, 170)">
              <use xlink:href="#testShape" fill="url(#rgTxfB)" />
              <text y="-30">(cx,cy)=(0%,0%) translate(.5,.5)</text>
          </g>
  
          <g transform="translate(0, 240)">
              <use xlink:href="#testShape" fill="url(#rgTxfC)" />
              <text y="-30">scale(.25,.5)</text>
          </g>
  
          <g transform="translate(0, 310)">
              <use xlink:href="#testShape" fill="url(#rgTxfD)" />
              <text y="-30">(fx,fy)=(0,0) scale(.5, .5)</text>
          </g>
  
          <g transform="translate(0, 380)">
              <use xlink:href="#testShape" fill="url(#rgFxFyA)" />
              <text y="-30">(fx,fy)=(cx, cy)=(0%, 100%)</text>
          </g>
  
  
          </g>
  
      </g>
  </svg>
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org