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><radialGradient> Test A</title>
<text class="title" x="50%" y="40"><radialGradient> 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