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/01/24 20:49:37 UTC

cvs commit: xml-batik/sources/org/apache/batik/gvt/filter BackgroundRable8Bit.java

deweese     01/01/24 11:49:36

  Modified:    sources/org/apache/batik/bridge SVGFeBlendElementBridge.java
                        SVGFeCompositeElementBridge.java
                        SVGFeMergeElementBridge.java
               sources/org/apache/batik/ext/awt
                        LinearGradientPaintContext.java
                        MultipleGradientPaintContext.java
               sources/org/apache/batik/ext/awt/image GraphicsUtil.java
               sources/org/apache/batik/ext/awt/image/renderable
                        CompositeRable.java CompositeRable8Bit.java
                        CompositeRule.java SVGComposite.java
               sources/org/apache/batik/gvt/filter BackgroundRable8Bit.java
  Log:
  1) CompositeRable now takes the colorspace compositing should be done in
     (currently support sRGB and linear sRGB).
  2) Total rewrite of LinearGradient code (should be much faster)
  3) Fixed MultipleGradientPaint so it works if the image is in linear sRGB
  4) GraphicsUtils optimizations fixed to anticipate linear sRGB images.
  5) BackgroundRable now does a much better job of optimizing it's rendering.
  6) SVGComposite now includes OVER, IN, OUT modes, since they are needed
     for linear images, and the built in general case from Java 2D sucks :)
  
  Revision  Changes    Path
  1.3       +2 -2      xml-batik/sources/org/apache/batik/bridge/SVGFeBlendElementBridge.java
  
  Index: SVGFeBlendElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGFeBlendElementBridge.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SVGFeBlendElementBridge.java	2001/01/24 05:39:11	1.2
  +++ SVGFeBlendElementBridge.java	2001/01/24 19:49:23	1.3
  @@ -43,7 +43,7 @@
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
    * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
  - * @version $Id: SVGFeBlendElementBridge.java,v 1.2 2001/01/24 05:39:11 vhardy Exp $
  + * @version $Id: SVGFeBlendElementBridge.java,v 1.3 2001/01/24 19:49:23 deweese Exp $
    */
   public class SVGFeBlendElementBridge implements FilterPrimitiveBridge,
                                                   SVGConstants {
  @@ -140,7 +140,7 @@
           Vector srcs = new Vector(2);
           srcs.add(in2);
           srcs.add(in1);
  -        filter = new CompositeRable8Bit(srcs, rule);
  +        filter = new CompositeRable8Bit(srcs, rule, true);
   
           filter = new PadRable8Bit(filter, blendArea, PadMode.ZERO_PAD);
   
  
  
  
  1.3       +2 -2      xml-batik/sources/org/apache/batik/bridge/SVGFeCompositeElementBridge.java
  
  Index: SVGFeCompositeElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGFeCompositeElementBridge.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SVGFeCompositeElementBridge.java	2001/01/24 05:39:12	1.2
  +++ SVGFeCompositeElementBridge.java	2001/01/24 19:49:24	1.3
  @@ -43,7 +43,7 @@
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
    * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
  - * @version $Id: SVGFeCompositeElementBridge.java,v 1.2 2001/01/24 05:39:12 vhardy Exp $
  + * @version $Id: SVGFeCompositeElementBridge.java,v 1.3 2001/01/24 19:49:24 deweese Exp $
    */
   public class SVGFeCompositeElementBridge implements FilterPrimitiveBridge,
                                                       SVGConstants {
  @@ -140,7 +140,7 @@
           Vector srcs = new Vector(2);
           srcs.add(in2);
           srcs.add(in1);
  -        filter = new CompositeRable8Bit(srcs, rule);
  +        filter = new CompositeRable8Bit(srcs, rule, true);
   
           filter = new PadRable8Bit(filter, compositeArea, PadMode.ZERO_PAD);
   
  
  
  
  1.3       +2 -2      xml-batik/sources/org/apache/batik/bridge/SVGFeMergeElementBridge.java
  
  Index: SVGFeMergeElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGFeMergeElementBridge.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SVGFeMergeElementBridge.java	2001/01/24 05:39:13	1.2
  +++ SVGFeMergeElementBridge.java	2001/01/24 19:49:25	1.3
  @@ -43,7 +43,7 @@
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
    * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
  - * @version $Id: SVGFeMergeElementBridge.java,v 1.2 2001/01/24 05:39:13 vhardy Exp $
  + * @version $Id: SVGFeMergeElementBridge.java,v 1.3 2001/01/24 19:49:25 deweese Exp $
    */
   public class SVGFeMergeElementBridge implements FilterPrimitiveBridge,
                                                   SVGConstants {
  @@ -139,7 +139,7 @@
                                                           uctx);
   
           Filter filter = null;
  -        filter = new CompositeRable8Bit(srcs, CompositeRule.OVER);
  +        filter = new CompositeRable8Bit(srcs, CompositeRule.OVER, false);
   
           filter = new PadRable8Bit(filter,
                                         primitiveRegion,
  
  
  
  1.2       +331 -16   xml-batik/sources/org/apache/batik/ext/awt/LinearGradientPaintContext.java
  
  Index: LinearGradientPaintContext.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/LinearGradientPaintContext.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LinearGradientPaintContext.java	2001/01/23 17:06:56	1.1
  +++ LinearGradientPaintContext.java	2001/01/24 19:49:27	1.2
  @@ -18,7 +18,7 @@
    * 
    * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: LinearGradientPaintContext.java,v 1.1 2001/01/23 17:06:56 tkormann Exp $
  + * @version $Id: LinearGradientPaintContext.java,v 1.2 2001/01/24 19:49:27 deweese Exp $
    * @see java.awt.PaintContext
    * @see java.awt.Paint
    * @see java.awt.GradientPaint
  @@ -115,7 +115,309 @@
           //constant, incorporates the translation components from the matrix
           gc = (a02-start.x)*constX + (a12-start.y)*constY;	       	
       }
  +
  +    protected void fillHardNoCycle(int[] pixels, int off, int adjust, 
  +                              int x, int y, int w, int h) {
  +
  +        //constant which can be pulled out of the inner loop
  +        final float initConst = (dgdX*x) + gc;
  +
  +        for(int i=0; i<h; i++) { //for every row
  +            //initialize current value to be start.
  +            float g = initConst + dgdY*(y+i); 
  +            final int rowLimit = off+w;  // end of row iteration
  +
  +            if (dgdX == 0) {
  +                if (g < 0) g = 0;
  +                if (g > 1) g = 1;
  +
  +                // Could be a binary search...
  +                int gradIdx = 0;
  +                while (gradIdx < gradientsLength) {
  +                    if (g < fractions[gradIdx+1])
  +                        break;
  +                    gradIdx++;
  +                }
  +
  +                float delta = (g-fractions[gradIdx]);
  +                float idx  = ((delta*GRADIENT_SIZE_INDEX)
  +                              /normalizedIntervals[gradIdx])+0.5f;
  +                final int val = gradients[gradIdx][(int)idx];
  +                while (off < rowLimit) {
  +                    pixels[off++] = val;
  +                }
  +            } else {
  +                int gradSteps;
  +                int preGradSteps;
  +                final int preVal, postVal;
  +                if (dgdX > 0) {
  +                    gradSteps    = (int)         ((1-g)/dgdX);
  +                    preGradSteps = (int)Math.ceil((0-g)/dgdX);
  +                    preVal  = gradients[0][0];
  +                    postVal = 
  +                        gradients[gradients.length-1][GRADIENT_SIZE_INDEX];
  +                } else { // dgdX < 0
  +                    gradSteps    = (int)         ((0-g)/dgdX);
  +                    preGradSteps = (int)Math.ceil((1-g)/dgdX);
  +                    preVal  = 
  +                        gradients[gradients.length-1][GRADIENT_SIZE_INDEX];
  +                    postVal = gradients[0][0];
  +                }
  +
  +                if (gradSteps > w) 
  +                    gradSteps = w;
  +                final int gradLimit    = off + gradSteps;
  +
  +                if (preGradSteps > 0) {
  +                    if (preGradSteps > w)
  +                        preGradSteps = w;
  +                    final int preGradLimit = off + preGradSteps;
  +
  +                    while (off < preGradLimit) {
  +                        pixels[off++] = preVal;
  +                    }
  +                    g += dgdX*preGradSteps;
  +                }
  +                        
  +                if (dgdX > 0) {
  +                    // Could be a binary search...
  +                    int gradIdx = 0;
  +                    while (gradIdx < gradientsLength) {
  +                        if (g < fractions[gradIdx+1])
  +                            break;
  +                        gradIdx++;
  +                    }
  +                    
  +                    while (off < gradLimit) {
  +                        float delta = (g-fractions[gradIdx]);
  +                        int [] grad = gradients[gradIdx];
  +
  +                        int steps = 
  +                            (int)Math.ceil((fractions[gradIdx+1]-g)/dgdX);
  +                        int subGradLimit = off + steps;
  +                        if (subGradLimit > gradLimit)
  +                            subGradLimit = gradLimit;
  +
  +                        int idx  = (int)(((delta*GRADIENT_SIZE_INDEX)
  +                                          /normalizedIntervals[gradIdx])
  +                                         *(1<<16)) + (1<<15);
  +                        int step = (int)(((dgdX*GRADIENT_SIZE_INDEX)
  +                                          /normalizedIntervals[gradIdx])
  +                                         *(1<<16));
  +                        while (off < subGradLimit) {
  +                            pixels[off++] = grad[idx>>16];
  +                            idx += step;
  +                        }
  +                        g+=dgdX*steps;
  +                        gradIdx++;
  +                    }
  +                } else {
  +                    // Could be a binary search...
  +                    int gradIdx = gradientsLength-1;
  +                    while (gradIdx >= 0) {
  +                        if (g > fractions[gradIdx])
  +                            break;
  +                        gradIdx--;
  +                    }
  +                    
  +                    while (off < gradLimit) {
  +                        float delta = (g-fractions[gradIdx]);
  +                        int [] grad = gradients[gradIdx];
  +
  +                        int steps        = (int)Math.ceil(delta/-dgdX);
  +                        int subGradLimit = off + steps;
  +                        if (subGradLimit > gradLimit)
  +                            subGradLimit = gradLimit;
  +
  +                        int idx  = (int)(((delta*GRADIENT_SIZE_INDEX)
  +                                          /normalizedIntervals[gradIdx])
  +                                         *(1<<16)) + (1<<15);
  +                        int step = (int)(((dgdX*GRADIENT_SIZE_INDEX)
  +                                          /normalizedIntervals[gradIdx])
  +                                         *(1<<16));
  +                        while (off < subGradLimit) {
  +                            pixels[off++] = grad[idx>>16];
  +                            idx += step;
  +                        }
  +                        g+=dgdX*steps;
  +                        gradIdx--;
  +                    }
  +                }
  +
  +                while (off < rowLimit) {
  +                    pixels[off++] = postVal;
  +                }
  +            }
  +            off += adjust; //change in off from row to row
  +        }
  +    }
  +
  +    protected void fillSimpleNoCycle(int[] pixels, int off, int adjust, 
  +                                int x, int y, int w, int h) {
  +        //constant which can be pulled out of the inner loop
  +        final float initConst = (dgdX*x) + gc;
  +        final float      step = dgdX*fastGradientArraySize;
  +        final int      fpStep = (int)(step*(1<<16));  // fix point step
  +
  +        for(int i=0; i<h; i++){ //for every row
  +            //initialize current value to be start.
  +            float g = initConst + dgdY*(y+i); 
  +            g *= fastGradientArraySize;
  +            g += 0.5; // rounding factor...
  +
  +            final int rowLimit = off+w;  // end of row iteration
  +
  +            if (dgdX == 0) {
  +                final int val = gradient[(int)g];
  +                while (off < rowLimit) {
  +                    pixels[off++] = val;
  +                }
  +            } else {
  +                int gradSteps;
  +                int preGradSteps;
  +                final int preVal, postVal;
  +                if (dgdX > 0) {
  +                    gradSteps = (int)((fastGradientArraySize-g)/step);
  +                    preGradSteps = (int)Math.ceil(0-g/step);
  +                    preVal  = gradient[0];
  +                    postVal = gradient[fastGradientArraySize];
  +
  +                } else { // dgdX < 0
  +                    gradSteps    = (int)((0-g)/step);
  +                    preGradSteps = 
  +                        (int)Math.ceil((fastGradientArraySize-g)/step);
  +                    preVal  = gradient[fastGradientArraySize];
  +                    postVal = gradient[0];
  +                }
  +
  +                if (gradSteps > w) 
  +                    gradSteps = w;
  +                final int gradLimit    = off + gradSteps;
  +
  +                if (preGradSteps > 0) {
  +                    if (preGradSteps > w)
  +                        preGradSteps = w;
  +                    final int preGradLimit = off + preGradSteps;
  +
  +                    while (off < preGradLimit) {
  +                        pixels[off++] = preVal;
  +                    }
  +                    g += step*preGradSteps;
  +                }
  +                        
  +                int fpG = (int)(g*(1<<16));
  +                while (off < gradLimit) {
  +                    pixels[off++] = gradient[fpG>>16];
  +                    fpG += fpStep;
  +                }
  +                        
  +                while (off < rowLimit) {
  +                    pixels[off++] = postVal;
  +                }
  +            }
  +            off += adjust; //change in off from row to row
  +        }
  +    }
       
  +    protected void fillSimpleRepeat(int[] pixels, int off, int adjust, 
  +                               int x, int y, int w, int h) {
  +
  +        final float initConst = (dgdX*x) + gc;
  +
  +        // Limit step to fractional part of
  +        // fastGradientArraySize (the non fractional part has
  +        // no affect anyways, and would mess up lots of stuff
  +        // below).
  +        float step = (dgdX - (int)dgdX)*fastGradientArraySize;
  +
  +                // Make it a Positive step (a small negative step is
  +                // the same as a positive step slightly less than
  +                // fastGradientArraySize.
  +        if (step < 0) 
  +            step += fastGradientArraySize;
  +
  +        for(int i=0; i<h; i++) { //for every row
  +            //initialize current value to be start.
  +            float g = initConst + dgdY*(y+i); 
  +
  +            // now Limited between -1 and 1.
  +            g = g-(int)g;
  +            // put in the positive side.
  +            if (g < 0)
  +                g += 1;
  +                        
  +            // scale for gradient array... 
  +            g *= fastGradientArraySize;
  +            g += 0.5; // rounding factor
  +            final int rowLimit = off+w;  // end of row iteration
  +            while (off < rowLimit) {
  +                int idx = (int)g;
  +                if (idx >= fastGradientArraySize) {
  +                    g   -= fastGradientArraySize;
  +                    idx -= fastGradientArraySize; 
  +                }
  +                pixels[off++] = gradient[idx];
  +                g += step;
  +            }
  +
  +            off += adjust; //change in off from row to row
  +        }
  +    }
  +
  +
  +    protected void fillSimpleReflect(int[] pixels, int off, int adjust, 
  +                                int x, int y, int w, int h) {
  +        final float initConst = (dgdX*x) + gc;
  +
  +        for (int i=0; i<h; i++) { //for every row
  +            //initialize current value to be start.
  +            float g = initConst + dgdY*(y+i); 
  +
  +            // now limited g to -2<->2
  +            g = g - 2*((int)(g/2.0f));
  +
  +            float step = dgdX;
  +            // Pull it into the positive half
  +            if (g < 0) {
  +                g = -g; //take absolute value
  +                step = - step;  // Change direction..
  +            }
  +
  +            // Now do the same for dgdX. This is safe because
  +            // any step that is a multiple of 2.0 has no
  +            // affect, hence we can remove it which the first
  +            // part does.  The second part simply adds 2.0
  +            // (which has no affect due to the cylcle) to move
  +            // all negative step values into the positive
  +            // side.
  +            step = step - 2*((int)step/2.0f);
  +            if (step < 0) 
  +                step += 2.0;
  +            final int reflectMax = 2*fastGradientArraySize;
  +
  +            // Scale for gradient array.
  +            g    *= fastGradientArraySize;
  +            g    += 0.5;
  +            step *= fastGradientArraySize;
  +            final int rowLimit = off+w;  // end of row iteration
  +            while (off < rowLimit) {
  +                int idx = (int)g;
  +                if (idx >= reflectMax) {
  +                    g   -= reflectMax;
  +                    idx -= reflectMax;
  +                }
  +
  +                if (idx <= fastGradientArraySize)
  +                    pixels[off++] = gradient[idx];
  +                else
  +                    pixels[off++] = gradient[reflectMax-idx];
  +                g+= step;
  +            }
  +
  +            off += adjust; //change in off from row to row
  +        }
  +    }
  +        
       /**
        * Return a Raster containing the colors generated for the graphics
        * operation.  This is where the area is filled with colors distributed
  @@ -128,23 +430,36 @@
       protected void fillRaster(int[] pixels, int off, int adjust, 
                                 int x, int y, int w, int h) {
   	
  -        float g = 0;     //current value for row gradients
  -	
  -        int rowLimit = off + w;  //Used to end iteration on rows   
  -	
           //constant which can be pulled out of the inner loop
  -        float initConst = (dgdX*x) + gc;
  -	
  -        for(int i=0; i<h; i++){ //for every row
  -            g = initConst + dgdY*(y+i); //initialize current value to be start.
  -	    
  -            while(off < rowLimit){ //for every pixel in this row.
  -                pixels[off++] = indexIntoGradientsArrays(g); //get the color
  -                g += dgdX; //incremental change in g
  +        final float initConst = (dgdX*x) + gc;
  +
  +        if (!isSimpleLookup) {
  +            if (cycleMethod == MultipleGradientPaint.NO_CYCLE) {
  +                fillHardNoCycle(pixels, off, adjust, x, y, w, h);
               }
  -	    
  -            off += adjust; //change in off from row to row
  -            rowLimit = off + w; //rowlimit is width + offset.
  +            else {
  +                //initialize current value to be start.
  +                for(int i=0; i<h; i++){ //for every row
  +                    float g = initConst + dgdY*(y+i); 
  +                
  +                    final int rowLimit = off+w;  // end of row iteration
  +                    while(off < rowLimit){ //for every pixel in this row.
  +                        //get the color
  +                        pixels[off++] = indexIntoGradientsArrays(g); 
  +                        g += dgdX; //incremental change in g
  +                    }
  +                    off += adjust; //change in off from row to row
  +                }
  +            }
  +        } else {
  +            // Simple implementations: just scale index by array size
  +            
  +            if (cycleMethod == MultipleGradientPaint.NO_CYCLE)
  +                fillSimpleNoCycle(pixels, off, adjust, x, y, w, h);
  +            else if (cycleMethod == MultipleGradientPaint.REPEAT)
  +                fillSimpleRepeat(pixels, off, adjust, x, y, w, h);
  +            else //cycleMethod == MultipleGradientPaint.REFLECT
  +                fillSimpleReflect(pixels, off, adjust, x, y, w, h);
           }
       }
       
  
  
  
  1.2       +103 -24   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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MultipleGradientPaintContext.java	2001/01/23 17:06:57	1.1
  +++ MultipleGradientPaintContext.java	2001/01/24 19:49:28	1.2
  @@ -9,6 +9,7 @@
   package org.apache.batik.ext.awt;
   
   import java.awt.*;
  +import java.awt.color.*;
   import java.awt.geom.*;
   import java.awt.image.*;
   import java.lang.ref.WeakReference;
  @@ -20,7 +21,7 @@
    *
    * @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.1 2001/01/23 17:06:57 tkormann Exp $
  + * @version $Id: MultipleGradientPaintContext.java,v 1.2 2001/01/24 19:49:28 deweese Exp $
    *
    */
   abstract class MultipleGradientPaintContext implements PaintContext {
  @@ -32,8 +33,26 @@
       protected ColorModel model;
   
       /** Color model used if gradient colors are all opaque */
  -    private static ColorModel xrgbmodel =
  -        new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
  +    private static ColorModel lrgbmodel_NA = new DirectColorModel
  +        (ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
  +         24, 0xff0000, 0xFF00, 0xFF, 0x0,
  +         false, DataBuffer.TYPE_INT);
  +
  +    private static ColorModel srgbmodel_NA = new DirectColorModel
  +        (ColorSpace.getInstance(ColorSpace.CS_sRGB),
  +         24, 0xff0000, 0xFF00, 0xFF, 0x0,
  +         false, DataBuffer.TYPE_INT);
  +
  +    /** Color model used if some gradient colors are transparent */
  +    private static ColorModel lrgbmodel_A = new DirectColorModel
  +        (ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB),
  +         32, 0xff0000, 0xFF00, 0xFF, 0xFF000000,
  +         false, DataBuffer.TYPE_INT);
  +
  +    private static ColorModel srgbmodel_A = new DirectColorModel
  +        (ColorSpace.getInstance(ColorSpace.CS_sRGB),
  +         32, 0xff0000, 0xFF00, 0xFF, 0xFF000000,
  +         false, DataBuffer.TYPE_INT);
   
        /** The cached colorModel */
       protected static ColorModel cachedModel;
  @@ -76,16 +95,19 @@
       /** Array of gradient arrays, one array for each interval.  Used by
        *  calculateMultipleArrayGradient().
        */
  -    private int[][] gradients;
  +    protected int[][] gradients;
   
  +    /** Length of the 2D slow lookup gradients array. */
  +    protected int gradientsLength;
  +
       /** Normalized intervals array */
  -    private float[] normalizedIntervals;
  +    protected float[] normalizedIntervals;
   
       /** fractions array */
  -    private float[] fractions;
  +    protected float[] fractions;
   
       /** Non-normalized intervals array */
  -    private float[] intervals;
  +    protected float[] intervals;
   
       /** Gradient colors */
       private Color[] colors;
  @@ -108,8 +130,8 @@
       /** Constant number of max colors between any 2 arbitrary colors.
        * Used for creating and indexing gradients arrays.
        */
  -    private static final int GRADIENT_SIZE = 256;
  -    private static final int GRADIENT_SIZE_INDEX = GRADIENT_SIZE -1;
  +    protected static final int GRADIENT_SIZE = 256;
  +    protected static final int GRADIENT_SIZE_INDEX = GRADIENT_SIZE -1;
   
       /** Maximum length of the fast single-array.  If the estimated array size
        * is greater than this, switch over to the slow lookup method.
  @@ -118,9 +140,6 @@
        */
       private static final int MAX_GRADIENT_ARRAY_SIZE = 5000;
   
  -    /** Length of the 2D slow lookup gradients array. */
  -    private int gradientsLength;
  -
      /** Constructor for superclass. Does some initialization, but leaves most
       * of the heavy-duty math for calculateGradient(), so the subclass may do
       * some other manipulation beforehand if necessary.  This is not possible
  @@ -270,6 +289,15 @@
           this.cycleMethod = cycleMethod;
           this.colorSpace = colorSpace;
   
  +
  +        // Setup an example Model, we may refine it later.
  +        if (cm.getColorSpace() == lrgbmodel_A.getColorSpace())
  +            model = lrgbmodel_A;
  +        else if (cm.getColorSpace() == srgbmodel_A.getColorSpace())
  +            model = srgbmodel_A;
  +        else 
  +            throw new IllegalArgumentException
  +                ("Unsupported ColorSpace for interpolation");
       }
   
   
  @@ -330,10 +358,12 @@
           }
   
           // Use the most 'economical' model.
  -        if((transparencyTest >>> 24) == 0xff)
  -            model = xrgbmodel;
  -        else
  -            model = ColorModel.getRGBdefault();
  +        if((transparencyTest >>> 24) == 0xff) {
  +            if (model.getColorSpace() == lrgbmodel_NA.getColorSpace())
  +                model = lrgbmodel_NA;
  +            else if (model.getColorSpace() == srgbmodel_NA.getColorSpace())
  +                model = srgbmodel_NA;
  +        }
       }
   
   
  @@ -405,10 +435,21 @@
           //if interpolation occurred in Linear RGB space, convert the
           //gradients back to SRGB using the lookup table
           if (colorSpace == LinearGradientPaint.LINEAR_RGB) {
  -
  -            for (int i = 0; i < gradient.length; i++) {
  -                gradient[i] = convertEntireColorLinearRGBtoSRGB(gradient[i]);
  +            if (model.getColorSpace() == 
  +                ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
  +                for (int i = 0; i < gradient.length; i++) {
  +                    gradient[i] = 
  +                        convertEntireColorLinearRGBtoSRGB(gradient[i]);
  +                }
               }
  +        } else {
  +            if (model.getColorSpace() == 
  +                ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)) {
  +                for (int i = 0; i < gradient.length; i++) {
  +                    gradient[i] = 
  +                        convertEntireColorSRGBtoLinearRGB(gradient[i]);
  +                }
  +            }
           }
   
           fastGradientArraySize = gradient.length - 1;
  @@ -463,13 +504,25 @@
           //if interpolation occurred in Linear RGB space, convert the
           //gradients back to SRGB using the lookup table
           if (colorSpace == LinearGradientPaint.LINEAR_RGB) {
  -
  -            for (int j = 0; j < gradients.length; j++) {
  -                for (int i = 0; i < gradients[j].length; i++) {
  -                    gradients[j][i] =
  -                        convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
  +            if (model.getColorSpace() == 
  +                ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
  +                for (int j = 0; j < gradients.length; j++) {
  +                    for (int i = 0; i < gradients[j].length; i++) {
  +                        gradients[j][i] =
  +                            convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
  +                    }
                   }
               }
  +        } else {
  +            if (model.getColorSpace() == 
  +                ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)) {
  +                for (int j = 0; j < gradients.length; j++) {
  +                    for (int i = 0; i < gradients[j].length; i++) {
  +                        gradients[j][i] =
  +                            convertEntireColorSRGBtoLinearRGB(gradients[j][i]);
  +                    }
  +                }
  +            }
           }
       }
   
  @@ -530,6 +583,32 @@
           r1 =  LinearRGBtoSRGB[r1];
           g1 =  LinearRGBtoSRGB[g1];
           b1 =  LinearRGBtoSRGB[b1];
  +
  +        //re-compact the components
  +        return ((a1 << 24) |
  +                (r1 << 16) |
  +                (g1 << 8) |
  +                b1);
  +    }
  +
  +    /** Yet another helper function.  This one extracts the color components
  +     * of an integer RGB triple, converts them from LinearRGB to SRGB, then
  +     * recompacts them into an int.
  +     */
  +    private int convertEntireColorSRGBtoLinearRGB(int rgb) {
  +
  +        int a1, r1, g1, b1; //color components
  +
  +        //extract red, green, blue components
  +        a1 = (rgb >> 24) & 0xff;
  +        r1 = (rgb >> 16) & 0xff;
  +        g1 = (rgb >> 8) & 0xff;
  +        b1 = rgb & 0xff;
  +
  +        //use the lookup table
  +        r1 =  SRGBtoLinearRGB[r1];
  +        g1 =  SRGBtoLinearRGB[g1];
  +        b1 =  SRGBtoLinearRGB[b1];
   
           //re-compact the components
           return ((a1 << 24) |
  
  
  
  1.3       +39 -19    xml-batik/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java
  
  Index: GraphicsUtil.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/GraphicsUtil.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- GraphicsUtil.java	2001/01/24 05:39:28	1.2
  +++ GraphicsUtil.java	2001/01/24 19:49:29	1.3
  @@ -61,7 +61,7 @@
    * implementations.
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
  - * @version $Id: GraphicsUtil.java,v 1.2 2001/01/24 05:39:28 vhardy Exp $
  + * @version $Id: GraphicsUtil.java,v 1.3 2001/01/24 19:49:29 deweese Exp $
    */
   public class GraphicsUtil {
   
  @@ -79,6 +79,15 @@
           ColorSpace g2dCS = g2dCM.getColorSpace();
   
           if (g2dCS != srcCM.getColorSpace()) {
  +            /*
  +            System.out.println("srcCS: " + srcCM.getColorSpace());
  +            System.out.println("g2dCS: " + g2dCS);
  +            System.out.println("sRGB: " + 
  +                               ColorSpace.getInstance(ColorSpace.CS_sRGB));
  +            System.out.println("LsRGB: " + 
  +                               ColorSpace.getInstance
  +                               (ColorSpace.CS_LINEAR_RGB));
  +            */
               if      (g2dCS == ColorSpace.getInstance(ColorSpace.CS_sRGB))
                   cr = convertTosRGB(cr);
               else if (g2dCS == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB))
  @@ -88,9 +97,9 @@
   
           ColorModel drawCM = srcCM;
           if ((drawCM.hasAlpha()) && (g2dCM.hasAlpha())) {
  -            if (drawCM.isAlphaPremultiplied() !=
  +            if (drawCM.isAlphaPremultiplied() != 
                   g2dCM .isAlphaPremultiplied())
  -                drawCM = coerceColorModel(drawCM,
  +                drawCM = coerceColorModel(drawCM, 
                                             g2dCM.isAlphaPremultiplied());
           }
   
  @@ -210,31 +219,42 @@
                   CompositeRable cr = (CompositeRable)filter;
                   // For the over mode we can just draw them in order...
                   if (cr.getCompositeRule() == CompositeRule.OVER) {
  -                    Vector srcs = cr.getSources();
  -                    Iterator i = srcs.iterator();
  -                    while (i.hasNext()) {
  -                        drawImage(g2d, (Filter)i.next());
  +                    ColorSpace crCS = cr.getCompositeColorSpace();
  +                    GraphicsConfiguration gc = g2d.getDeviceConfiguration();
  +                    ColorModel g2dCM = gc.getColorModel();
  +                    ColorSpace g2dCS = g2dCM.getColorSpace();
  +                    if (g2dCS == crCS) {
  +                        Vector srcs = cr.getSources();
  +                        Iterator i = srcs.iterator();
  +                        while (i.hasNext()) {
  +                            drawImage(g2d, (Filter)i.next());
  +                        }
  +                        return;
                       }
  -                    return;
                   }
               }
               else if (filter instanceof GraphicsNodeRable) {
                   GraphicsNodeRable gnr = (GraphicsNodeRable)filter;
  -                if (gnr.getUsePrimitivePaint()) {
  -                    gnr.getGraphicsNode().primitivePaint
  -                        (g2d, GraphicsNodeRenderContext.
  -                         getGraphicsNodeRenderContext(g2d));
  -                } else {
  -                    try {
  -                        gnr.getGraphicsNode().paint
  +                GraphicsConfiguration gc = g2d.getDeviceConfiguration();
  +                ColorModel g2dCM = gc.getColorModel();
  +                ColorSpace g2dCS = g2dCM.getColorSpace();
  +                if (g2dCS == ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
  +                    if (gnr.getUsePrimitivePaint()) {
  +                        gnr.getGraphicsNode().primitivePaint
                               (g2d, GraphicsNodeRenderContext.
                                getGraphicsNodeRenderContext(g2d));
  -                    } catch (InterruptedException ie) {
  -                        // Don't do anything we just return...
  +                    } else {
  +                        try {
  +                            gnr.getGraphicsNode().paint
  +                                (g2d, GraphicsNodeRenderContext.
  +                                 getGraphicsNodeRenderContext(g2d));
  +                        } catch (InterruptedException ie) {
  +                            // Don't do anything we just return...
  +                        }
                       }
  +                    // Primitive Paint did the work...
  +                    return;
                   }
  -                // Primitive Paint did the work...
  -                return;
               }
               else if (filter instanceof FilterChainRable) {
                   FilterChainRable fcr = (FilterChainRable)filter;
  
  
  
  1.2       +16 -2     xml-batik/sources/org/apache/batik/ext/awt/image/renderable/CompositeRable.java
  
  Index: CompositeRable.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/CompositeRable.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CompositeRable.java	2001/01/24 05:39:30	1.1
  +++ CompositeRable.java	2001/01/24 19:49:31	1.2
  @@ -9,13 +9,14 @@
   package org.apache.batik.ext.awt.image.renderable;
   
   import java.util.List;
  +import java.awt.color.ColorSpace;
   
   /**
    * Composites a list of images according to a single composite rule.
    * the image are applied in the order they are in the List given.
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
  - * @version $Id: CompositeRable.java,v 1.1 2001/01/24 05:39:30 vhardy Exp $
  + * @version $Id: CompositeRable.java,v 1.2 2001/01/24 19:49:31 deweese Exp $
    */
   public interface CompositeRable extends Filter {
         /**
  @@ -32,7 +33,20 @@
   
         /**
          * Get the composite rule in use for combining the sources.
  -       * @returns Composite rule currently in use.
  +       * @return Composite rule currently in use.
          */
       public CompositeRule getCompositeRule();
  +
  +      /**
  +       * Set the colorspace to perform compositing in
  +       * @param cs ColorSpace to use.
  +       */
  +    public void setCompositeColorSpace(ColorSpace cs);
  +
  +      /**
  +       * Get the colorspace to that compositing will be performed in
  +       * @return ColorSpace for compositing.
  +       */
  +    public ColorSpace getCompositeColorSpace();
  +
   }
  
  
  
  1.2       +119 -28   xml-batik/sources/org/apache/batik/ext/awt/image/renderable/CompositeRable8Bit.java
  
  Index: CompositeRable8Bit.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/CompositeRable8Bit.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CompositeRable8Bit.java	2001/01/24 05:39:30	1.1
  +++ CompositeRable8Bit.java	2001/01/24 19:49:31	1.2
  @@ -13,6 +13,9 @@
   import java.util.List;
   import java.util.Iterator;
   
  +import java.awt.color.ColorSpace;
  +import java.awt.Composite;
  +import java.awt.CompositeContext;
   import java.awt.Shape;
   import java.awt.Rectangle;
   import java.awt.Graphics2D;
  @@ -22,7 +25,9 @@
   import java.awt.geom.AffineTransform;
   
   import java.awt.image.BufferedImage;
  +import java.awt.image.Raster;
   import java.awt.image.RenderedImage;
  +import java.awt.image.WritableRaster;
   
   import java.awt.image.renderable.RenderContext;
   
  @@ -36,19 +41,27 @@
    * the image are applied in the order they are in the List given.
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
  - * @version $Id: CompositeRable8Bit.java,v 1.1 2001/01/24 05:39:30 vhardy Exp $
  + * @version $Id: CompositeRable8Bit.java,v 1.2 2001/01/24 19:49:31 deweese Exp $
    */
   public class CompositeRable8Bit
       extends    AbstractRable
       implements CompositeRable {
   
       protected CompositeRule rule;
  +    protected ColorSpace    colorspace;
  +    protected boolean       csIsLinear;
   
       public CompositeRable8Bit(List srcs,
  -                                  CompositeRule rule) {
  +                              CompositeRule rule,
  +                              boolean csIsLinear) {
           super(srcs);
   
           this.rule = rule;
  +        this.csIsLinear = csIsLinear;
  +        if (csIsLinear)
  +            colorspace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
  +        else
  +            colorspace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
       }
   
         /**
  @@ -70,14 +83,40 @@
   
         /**
          * Get the composite rule in use for combining the sources.
  -       * @returns Composite rule currently in use.
  +       * @return Composite rule currently in use.
          */
       public CompositeRule getCompositeRule() {
           return this.rule;
       }
   
  +      /**
  +       * Set the colorspace to perform compositing in
  +       * @param cs ColorSpace to use.
  +       */
  +    public void setCompositeColorSpace(ColorSpace cs) {
  +        touch();
  +        if (cs == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB))
  +            csIsLinear = true;
  +        else if (cs == ColorSpace.getInstance(ColorSpace.CS_sRGB))
  +            csIsLinear = false;
  +        else
  +            throw new IllegalArgumentException
  +                ("Unsupported ColorSpace for Composite: " + cs);
  +        this.colorspace = cs;
  +    }
  +
  +      /**
  +       * Get the colorspace to that compositing will be performed in
  +       * @return ColorSpace for compositing.
  +       */
  +    public ColorSpace getCompositeColorSpace() {
  +        return this.colorspace;
  +    }
  +
   
       protected RenderedImage createRenderingOver(RenderContext rc) {
  +        // System.out.println("Rendering Over: " + rule);
  +
           // Just copy over the rendering hints.
           RenderingHints rh = rc.getRenderingHints();
           if (rh == null) rh = new RenderingHints(null);
  @@ -97,25 +136,29 @@
   
               Rectangle2D.intersect(r, aoiR, r);
           }
  -
  -        AffineTransform translate = 
  -            AffineTransform.getTranslateInstance(-r.x, -r.y);
   
  -        BufferedImage bi = GraphicsUtil.makeLinearBufferedImage
  +        BufferedImage bi;
  +        if (csIsLinear)
  +            bi = GraphicsUtil.makeLinearBufferedImage
               (r.width, r.height, true);
  +        else
  +            bi = new BufferedImage(r.width, r.height, 
  +                                   BufferedImage.TYPE_INT_ARGB_PRE);
   
           Graphics2D g2d = bi.createGraphics();
   
           // Make sure we draw with what hints we have.
           g2d.setRenderingHints(rh);
  -        g2d.setTransform(translate);
  -        g2d.transform(at);
  +        g2d.translate(-r.x, -r.y);
  +        if (at != null)
  +            g2d.transform(at);
   
           Iterator i = srcs.iterator();
           while (i.hasNext()) {
               GraphicsUtil.drawImage(g2d, (Filter)i.next());
           }
   
  +        // System.out.println("Done Over: " + rule);
           return new BufferedImageCachableRed(bi, r.x, r.y);
       }
   
  @@ -133,6 +176,8 @@
           if (rule == CompositeRule.OVER)
               return createRenderingOver(rc);
   
  +        // System.out.println("Rendering General: " + rule);
  +
           // Just copy over the rendering hints.
           RenderingHints rh = rc.getRenderingHints();
           if (rh == null) rh = new RenderingHints(null);
  @@ -140,28 +185,45 @@
           // update the current affine transform
           AffineTransform at = rc.getTransform();
   
  -        Shape aoi = rc.getAreaOfInterest();
  -        if (aoi == null) aoi = getBounds2D();
  +        Rectangle2D aoi = rc.getAreaOfInterest().getBounds2D();
  +        if (aoi == null) 
  +            aoi = getBounds2D();
  +        else {
  +            Rectangle2D bounds2d = getBounds2D();
  +            if (bounds2d.intersects(aoi) == false)
  +                return null;
  +                
  +            Rectangle2D.intersect(aoi, bounds2d, aoi);
  +        }
   
  -        // AOI bounds in device space...
  +        // AOI bounds in device space.  Ideally we would limit r to
  +        // the actual region needed based on the current mode.  So for
  +        // IN we only need the intersection of all source.  For OUT we
  +        // only need the region under the last source (most of the
  +        // rest are r so I don't worry about it too much).
           Rectangle r = at.createTransformedShape(aoi).getBounds();
   
  -        if ((r.width <= 0) || (r.height <= 0))
  -            return null;
  +        BufferedImage bi;
  +        if (csIsLinear)
  +            bi = GraphicsUtil.makeLinearBufferedImage
  +            (r.width, r.height, true);
  +        else
  +            bi = new BufferedImage(r.width, r.height, 
  +                                   BufferedImage.TYPE_INT_ARGB_PRE);
   
  -        // I originally had this be premultipled but someone was
  -        // multiplying the alpha each time a composite was done (I'm
  -        // guessing it was trying to unmultiply composite, remultiply,
  -        // but the unmultiply failed to do anything...).
  -        BufferedImage bi = GraphicsUtil.makeLinearBufferedImage
  -            (r.width, r.height, false);
  +        WritableRaster wr = bi.getRaster();
   
  +        Composite comp = new SVGComposite(rule);
  +
           Graphics2D g2d = bi.createGraphics();
  -        g2d.translate(-r.x, -r.y);
   
           // Make sure we draw with what hints we have.
           g2d.setRenderingHints(rh);
  +        g2d.setComposite(comp);
  +        g2d.translate(-r.x, -r.y);
   
  +        rc = new RenderContext(at, aoi, rh);
  +        
           Iterator i = srcs.iterator();
           boolean first = true;
           while (i.hasNext()) {
  @@ -170,28 +232,57 @@
   
               // Get our sources image...
               RenderedImage ri = filt.createRendering(rc);
  -            // No output image keep going...
  +            // No output image keep going
  +            // FIXX: Should we do something different for IN/OUT/ARITH???
               if (ri == null)
                   continue;
  -            CachableRed cr = RenderedImageCachableRed.wrap(ri);
  -            cr = GraphicsUtil.convertToLsRGB(cr);
  +            CachableRed cr;
  +            cr = GraphicsUtil.wrap(ri);
   
  +            if (csIsLinear)
  +                cr = GraphicsUtil.convertToLsRGB(cr);
  +            else
  +                cr = GraphicsUtil.convertTosRGB(cr);
  +
               if ((ri.getMinX()   != r.x)     || (ri.getMinY()   != r.y) ||
                   (ri.getWidth()  != r.width) || (ri.getHeight() != r.height)) {
                   cr = new PadRed(cr, r, PadMode.ZERO_PAD, rh);
               }
   
  -            GraphicsUtil.drawImage(g2d, cr);
  -
               if (first) {
  -                  // After the first image we set the composite rule.
  -                g2d.setComposite(new SVGComposite(rule));
  +                wr = wr.createWritableTranslatedChild(r.x, r.y);
  +                cr.copyData(wr);
  +                if (cr.getColorModel().isAlphaPremultiplied() == false) {
  +                    GraphicsUtil.coerceData(wr, cr.getColorModel(), true);
  +                }
  +                wr = bi.getRaster();
                   first = false;
  +            } else {
  +
  +                // If I allow any of the other modes to fall into
  +                // the draw case they fail miserably.  But OVER
  +                // is used alot and is significantly faster in the
  +                // draw case, and works as long as the source and dest
  +                // colorspace match (which the always will here).
  +                if (csIsLinear && (rule != CompositeRule.OVER)) {
  +                    // System.out.println("In manual");
  +                    Raster ras = cr.getData(r);
  +                    ras = ras.createTranslatedChild(0,0);
  +                    CompositeContext compCont;
  +                    compCont = comp.createContext(cr.getColorModel(),
  +                                                  bi.getColorModel(),
  +                                                  rh);
  +                    compCont.compose(ras, wr, wr);
  +                } else {
  +                    // System.out.println("In Draw");
  +                    GraphicsUtil.drawImage(g2d, cr);
  +                }
               }
                           
   
           }
   
  +        // System.out.println("Done General: " + rule);
           return new BufferedImageCachableRed(bi, r.x, r.y);
       }
   }
  
  
  
  1.2       +36 -1     xml-batik/sources/org/apache/batik/ext/awt/image/renderable/CompositeRule.java
  
  Index: CompositeRule.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/CompositeRule.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CompositeRule.java	2001/01/24 05:39:30	1.1
  +++ CompositeRule.java	2001/01/24 19:49:32	1.2
  @@ -13,7 +13,7 @@
    * the CompositeRable operation. (over, in, out, atop, xor, arith)
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
  - * @version $Id: CompositeRule.java,v 1.1 2001/01/24 05:39:30 vhardy Exp $
  + * @version $Id: CompositeRule.java,v 1.2 2001/01/24 19:49:32 deweese Exp $
    */
   public final class CompositeRule implements java.io.Serializable {
   
  @@ -237,6 +237,41 @@
               return DARKEN;
           case RULE_LIGHTEN:
               return LIGHTEN;
  +        default:
  +            throw new Error("Unknown Composite Rule type");
  +        }
  +    }
  +
  +    /**
  +     * This is called by the serialization code before it returns
  +     * an unserialized object. To provide for unicity of
  +     * instances, the instance that was read is replaced by its
  +     * static equivalent. See the serialiazation specification for
  +     * further details on this method's logic.
  +     */
  +    public String toString() {
  +        switch(rule){
  +        case RULE_OVER:
  +            return "[CompositeRule: OVER]";
  +        case RULE_IN:
  +            return "[CompositeRule: IN]";
  +        case RULE_OUT:
  +            return "[CompositeRule: OUT]";
  +        case RULE_ATOP:
  +            return "[CompositeRule: ATOP]";
  +        case RULE_XOR:
  +            return "[CompositeRule: XOR]";
  +        case RULE_ARITHMETIC:
  +            return ("[CompositeRule: ARITHMATIC k1:" +
  +                    k1 + " k2: " + k2 + " k3: " + k3 + " k4: " + k4 + "]");
  +        case RULE_MULTIPLY:
  +            return "[CompositeRule: MULTIPLY]";
  +        case RULE_SCREEN:
  +            return "[CompositeRule: SCREEN]";
  +        case RULE_DARKEN:
  +            return "[CompositeRule: DARKEN]";
  +        case RULE_LIGHTEN:
  +            return "[CompositeRule: LIGHTEN]";
           default:
               throw new Error("Unknown Composite Rule type");
           }
  
  
  
  1.2       +145 -13   xml-batik/sources/org/apache/batik/ext/awt/image/renderable/SVGComposite.java
  
  Index: SVGComposite.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/SVGComposite.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SVGComposite.java	2001/01/24 05:39:34	1.1
  +++ SVGComposite.java	2001/01/24 19:49:33	1.2
  @@ -13,6 +13,7 @@
   import java.awt.CompositeContext;
   import java.awt.RenderingHints;
   
  +import java.awt.color.ColorSpace;
   import java.awt.image.ColorModel;
   import java.awt.image.Raster;
   import java.awt.image.WritableRaster;
  @@ -25,7 +26,7 @@
    * This provides an implementation of all the composite rules in SVG.
    *
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
  - * @version $Id: SVGComposite.java,v 1.1 2001/01/24 05:39:34 vhardy Exp $
  + * @version $Id: SVGComposite.java,v 1.2 2001/01/24 19:49:33 deweese Exp $
    */
   public class SVGComposite
       implements Composite {
  @@ -39,19 +40,31 @@
       public CompositeContext createContext(ColorModel srcCM,
                                             ColorModel dstCM,
                                             RenderingHints hints) {
  +        if (false) {
  +            ColorSpace srcCS = srcCM.getColorSpace();
  +            ColorSpace dstCS = dstCM.getColorSpace();
  +            System.out.println("srcCS: " + srcCS);
  +            System.out.println("dstCS: " + dstCS);
  +            System.out.println
  +                ("lRGB: " + ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB));
  +            System.out.println
  +                ("sRGB: " + ColorSpace.getInstance(ColorSpace.CS_sRGB));
  +        }
           switch (rule.getRule()) {
           case CompositeRule.RULE_OVER:
  -            return AlphaComposite.SrcOver.createContext(srcCM, dstCM, hints);
  +            return new OverCompositeContext(srcCM, dstCM);
  +
           case CompositeRule.RULE_IN:
  -            return AlphaComposite.SrcIn.  createContext(srcCM, dstCM, hints);
  +            return new InCompositeContext  (srcCM, dstCM);
  +
           case CompositeRule.RULE_OUT:
  -            return AlphaComposite.SrcOut. createContext(srcCM, dstCM, hints);
  +            return new OutCompositeContext (srcCM, dstCM);
   
           case CompositeRule.RULE_ATOP:
               return new AtopCompositeContext(srcCM, dstCM);
   
           case CompositeRule.RULE_XOR:
  -            return new XorCompositeContext(srcCM, dstCM);
  +            return new XorCompositeContext (srcCM, dstCM);
   
           case CompositeRule.RULE_ARITHMETIC:
               float [] coeff = rule.getCoefficients();
  @@ -106,7 +119,6 @@
                   dstPreCM = GraphicsUtil.coerceData((WritableRaster)dstIn,
                                                      dstCM, true);
   
  -            
               precompose(src, dstIn, dstOut);
   
               if (!srcCM.isAlphaPremultiplied())
  @@ -123,6 +135,120 @@
           }
       }
   
  +    public static class OverCompositeContext 
  +        extends AlphaPreCompositeContext {
  +        OverCompositeContext(ColorModel srcCM, ColorModel dstCM) {
  +            super(srcCM, dstCM);
  +        }
  +
  +        public void precompose(Raster src, Raster dstIn, 
  +                               WritableRaster dstOut) {
  +            int [] srcPix = null;
  +            int [] dstPix = null;
  +
  +            int x=dstOut.getMinX();
  +            int w=dstOut.getWidth();
  +
  +            int y0=dstOut.getMinY();
  +            int y1=y0 + dstOut.getHeight();
  +
  +            final int norm = (1<<24)/255;
  +            final int pt5  = (1<<23);
  +
  +            for (int y = y0; y<y1; y++) {
  +                srcPix = src.getPixels  (x, y, w, 1, srcPix);
  +                dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
  +                int sp  = 0;
  +                int end = w*4;
  +                while(sp<end) {
  +                    final int dstM = (255-srcPix[sp+3])*norm;
  +                    dstPix[sp] =(srcPix[sp] + dstPix[sp]*dstM +pt5)>>>24; ++sp;
  +                    dstPix[sp] =(srcPix[sp] + dstPix[sp]*dstM +pt5)>>>24; ++sp;
  +                    dstPix[sp] =(srcPix[sp] + dstPix[sp]*dstM +pt5)>>>24; ++sp;
  +                    dstPix[sp] =(srcPix[sp] + dstPix[sp]*dstM +pt5)>>>24; ++sp;
  +                }
  +                dstOut.setPixels(x, y, w, 1, dstPix);
  +            }
  +
  +        }
  +    }
  +
  +    public static class InCompositeContext 
  +        extends AlphaPreCompositeContext {
  +        InCompositeContext(ColorModel srcCM, ColorModel dstCM) {
  +            super(srcCM, dstCM);
  +        }
  +
  +        public void precompose(Raster src, Raster dstIn, 
  +                               WritableRaster dstOut) {
  +            int [] srcPix = null;
  +            int [] dstPix = null;
  +
  +            int x=dstOut.getMinX();
  +            int w=dstOut.getWidth();
  +
  +            int y0=dstOut.getMinY();
  +            int y1=y0 + dstOut.getHeight();
  +
  +            final int norm = (1<<24)/255;
  +            final int pt5  = (1<<23);
  +
  +            for (int y = y0; y<y1; y++) {
  +                srcPix = src.getPixels  (x, y, w, 1, srcPix);
  +                dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
  +                int sp  = 0;
  +                int end = w*4;
  +                while(sp<end) {
  +                    final int srcM = dstPix[sp+3]*norm;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                }
  +                dstOut.setPixels(x, y, w, 1, dstPix);
  +            }
  +
  +        }
  +    }
  +
  +    public static class OutCompositeContext 
  +        extends AlphaPreCompositeContext {
  +        OutCompositeContext(ColorModel srcCM, ColorModel dstCM) {
  +            super(srcCM, dstCM);
  +        }
  +
  +        public void precompose(Raster src, Raster dstIn, 
  +                               WritableRaster dstOut) {
  +            int [] srcPix = null;
  +            int [] dstPix = null;
  +
  +            int x=dstOut.getMinX();
  +            int w=dstOut.getWidth();
  +
  +            int y0=dstOut.getMinY();
  +            int y1=y0 + dstOut.getHeight();
  +
  +            final int norm = (1<<24)/255;
  +            final int pt5  = (1<<23);
  +
  +            for (int y = y0; y<y1; y++) {
  +                srcPix = src.getPixels  (x, y, w, 1, srcPix);
  +                dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
  +                int sp  = 0;
  +                int end = w*4;
  +                while(sp<end) {
  +                    final int srcM = (255-dstPix[sp+3])*norm;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                    dstPix[sp] = (srcPix[sp]*srcM + pt5)>>>24; ++sp;
  +                }
  +                dstOut.setPixels(x, y, w, 1, dstPix);
  +            }
  +
  +        }
  +    }
  +
       public static class AtopCompositeContext 
           extends AlphaPreCompositeContext {
           AtopCompositeContext(ColorModel srcCM, ColorModel dstCM) {
  @@ -141,6 +267,8 @@
               int y1=y0 + dstOut.getHeight();
   
               final int norm = (1<<24)/255;
  +            final int pt5  = (1<<23);
  +
               for (int y = y0; y<y1; y++) {
                   srcPix = src.getPixels  (x, y, w, 1, srcPix);
                   dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
  @@ -149,10 +277,12 @@
                   while(sp<end) {
                       final int srcM = (    dstPix[sp+3])*norm;
                       final int dstM = (255-srcPix[sp+3])*norm;
  -                    dstPix[sp] =(srcPix[sp]*srcM + dstPix[sp]*dstM)>>>24; ++sp;
  -                    dstPix[sp] =(srcPix[sp]*srcM + dstPix[sp]*dstM)>>>24; ++sp;
  -                    dstPix[sp] =(srcPix[sp]*srcM + dstPix[sp]*dstM)>>>24; ++sp;
  +                    dstPix[sp] =(srcPix[sp]*srcM + dstPix[sp]*dstM +pt5)>>>24;
  +                    ++sp;
  +                    dstPix[sp] =(srcPix[sp]*srcM + dstPix[sp]*dstM +pt5)>>>24;
                       ++sp;
  +                    dstPix[sp] =(srcPix[sp]*srcM + dstPix[sp]*dstM +pt5)>>>24;
  +                    sp+=2;
                   }
                   dstOut.setPixels(x, y, w, 1, dstPix);
               }
  @@ -179,6 +309,8 @@
               int y1=y0 + dstOut.getHeight();
   
               final int norm = (1<<24)/255;
  +            final int pt5  = (1<<23);
  +
               for (int y = y0; y<y1; y++) {
                   srcPix = src.getPixels  (x, y, w, 1, srcPix);
                   dstPix = dstIn.getPixels(x, y, w, 1, dstPix);
  @@ -189,13 +321,13 @@
                       final int dstM = (255-srcPix[sp+3])*norm;
   
                       dstPix[sp] = (srcPix[sp]*srcM + 
  -                                  dstPix[sp]*dstM)>>>24; ++sp;
  +                                  dstPix[sp]*dstM + pt5)>>>24; ++sp;
                       dstPix[sp] = (srcPix[sp]*srcM + 
  -                                  dstPix[sp]*dstM)>>>24; ++sp;
  +                                  dstPix[sp]*dstM + pt5)>>>24; ++sp;
                       dstPix[sp] = (srcPix[sp]*srcM + 
  -                                  dstPix[sp]*dstM)>>>24; ++sp;
  +                                  dstPix[sp]*dstM + pt5)>>>24; ++sp;
                       dstPix[sp] = (srcPix[sp]*srcM + 
  -                                  dstPix[sp]*dstM)>>>24; ++sp;
  +                                  dstPix[sp]*dstM + pt5)>>>24; ++sp;
                   }
                   dstOut.setPixels(x, y, w, 1, dstPix);
               }
  
  
  
  1.2       +29 -23    xml-batik/sources/org/apache/batik/gvt/filter/BackgroundRable8Bit.java
  
  Index: BackgroundRable8Bit.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/filter/BackgroundRable8Bit.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BackgroundRable8Bit.java	2001/01/24 05:39:48	1.1
  +++ BackgroundRable8Bit.java	2001/01/24 19:49:35	1.2
  @@ -43,7 +43,7 @@
    * createRendering methods.
    *
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: BackgroundRable8Bit.java,v 1.1 2001/01/24 05:39:48 vhardy Exp $
  + * @version $Id: BackgroundRable8Bit.java,v 1.2 2001/01/24 19:49:35 deweese Exp $
    */
   public class BackgroundRable8Bit
       extends    AbstractRable {
  @@ -239,7 +239,8 @@
        */
       public Filter getBackground(GraphicsNode gn,
                                   GraphicsNode child,
  -                                GraphicsNodeRenderContext rc) {
  +                                GraphicsNodeRenderContext rc,
  +                                Rectangle2D aoi) {
           if (gn == null) {
               throw new IllegalArgumentException
                   ("BackgroundImage requested yet no parent has " +
  @@ -254,7 +255,9 @@
   
           Vector srcs = new Vector();
           if (r2d == null) {
  -            Filter f = getBackground(gn.getParent(), gn, rc);
  +            AffineTransform at = gn.getTransform();
  +            Rectangle2D paoi = at.createTransformedShape(aoi).getBounds2D();
  +            Filter f = getBackground(gn.getParent(), gn, rc, paoi);
               if (f != null)
                 srcs.add(f);
           }
  @@ -273,20 +276,18 @@
                   //                    "\n  ChildGN: " + childGN);
                   if (childGN == child)
                       break;
  -                GraphicsNodeRable gnr;
  -                gnr  = gnrf.createGraphicsNodeRable(childGN, rc);
  -                gnr.setUsePrimitivePaint(false);
  -                srcs.add(gnr);
  +
  +                AffineTransform at = childGN.getTransform();
  +                Rectangle2D cbounds = childGN.getBounds(rc);
  +                cbounds = at.createTransformedShape(cbounds).getBounds2D();
  +                if (aoi.intersects(cbounds)) {
  +                    GraphicsNodeRable gnr;
  +                    gnr  = gnrf.createGraphicsNodeRable(childGN, rc);
  +                    gnr.setUsePrimitivePaint(false);
  +                    srcs.add(gnr);
  +                }
               }
           }
  -        /*  If this is uncommented then children appear in background img.
  -        else {
  -            // System.out.println("Parent: "      + gn);
  -            GraphicsNodeRable gnr;
  -            gnr  = gnrf.createGraphicsNodeRable(gn);
  -            srcs.add(gnr);
  -        }
  -        */
   
           if (srcs.size() == 0)
               return null;
  @@ -295,7 +296,7 @@
           if (srcs.size() == 1)
               ret = (Filter)srcs.get(0);
           else
  -            ret = new CompositeRable8Bit(srcs, CompositeRule.OVER);
  +            ret = new CompositeRable8Bit(srcs, CompositeRule.OVER, false);
   
           if (child != null) {
               // We are returning the filter to child so make
  @@ -345,16 +346,21 @@
           GraphicsNodeRenderContext gnrc;
           gnrc = GraphicsNodeRenderContext.
               getGraphicsNodeRenderContext(renderContext);
  +
  +        Rectangle2D r2d = getBounds2D();
   
  -        Filter f = getBackground(node, null, gnrc);
  +        Shape aoi = renderContext.getAreaOfInterest();
  +        if (aoi != null) {
  +            Rectangle2D aoiR2d = aoi.getBounds2D();
  +            if (r2d.intersects(aoiR2d) == false)
  +                return null;
  +            Rectangle2D.intersect(r2d, aoiR2d, r2d);
  +        }
  +
  +        Filter f = getBackground(node, null, gnrc, r2d);
  +
           if ( f == null)
               return null;
  -        // org.apache.batik.test.gvt.ImageDisplay.showImage
  -        //     ("PrePad", f.createRendering(renderContext));
  -
  -        Rectangle2D r2d = getBounds2D();
  -        // f = new PadRable8Bit(f, r2d, PadMode.ZERO_PAD);
  -        // System.out.println("Bounds: " + r2d);
   
           RenderedImage ri = f.createRendering(renderContext);
           return ri;