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 2002/12/10 17:19:19 UTC
cvs commit: xml-batik/test-resources/org/apache/batik/test samplesRendering.xml
deweese 2002/12/10 08:19:17
Modified: sources/org/apache/batik/ext/awt
LinearGradientPaintContext.java
MultipleGradientPaintContext.java
RadialGradientPaintContext.java
test-resources/org/apache/batik/test samplesRendering.xml
Added: samples/tests/spec/paints linearGradientRepeat.svg
Log:
1) Added Anti-aliasing for linear gradients when appropriate rendering
hints are set (render quality or color rendering quality).
2) Fixed a bug in the anti-alias gradient lookup code.
3) Improved the anti-aliasing alg in radial gradients.
4) Added an additional test for linear gradients.
Revision Changes Path
1.1 xml-batik/samples/tests/spec/paints/linearGradientRepeat.svg
Index: linearGradientRepeat.svg
===================================================================
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.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 deweese@apache.org -->
<!-- @author vhardy@apache.org -->
<!-- @version $Id: linearGradientRepeat.svg,v 1.1 2002/12/10 16:19:16 deweese Exp $ -->
<!-- ====================================================================== -->
<?xml-stylesheet type="text/css" href="../../resources/style/test.css" ?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="body" width="450" height="500" viewBox="0 0 450 500">
<title><linearGradient> Repeat Test</title>
<text class="title" x="50%" y="40">
<linearGradient> Repeat Test
</text>
<style type="text/css"><![CDATA[
.speed { clip-path:url(#speedClip); color-rendering:optimizeSpeed; }
.default { clip-path:url(#defaultClip); color-rendering:auto; }
.quality { clip-path:url(#qualityClip);
color-rendering:optimizeQuality; }
.saqLabel { font-family: Verdana, Helvetica;
font-size: 5;
text-anchor: middle;
fill:black; stroke:none;}
.line { fill:none; stroke:black; stroke-width:0.25; }
]]></style>
<defs>
<!-- Shape filled by linear gradients -->
<g id="testShape">
<rect x="-25" y="-20" width="50" height="40"
class="quality" />
<rect x="-25" y="-20" width="50" height="40"
class="default" />
<rect x="-25" y="-20" width="50" height="40"
class="speed" />
<text x="-16.5" y="24" class="saqLabel">Q</text>
<line x1="-8" x2="-8" y1="20" y2="25" class="line" />
<text x="0" y="24" class="saqLabel">A</text>
<line x1="8" x2="8" y1="20" y2="25" class="line" />
<text x="16.5" y="24" class="saqLabel">S</text>
</g>
<!-- Clip paths for the various color-rendering settings... -->
<clipPath id="qualityClip">
<rect x="-25" y="-20" width="17" height="40"/>
</clipPath>
<clipPath id="defaultClip">
<rect x="-8" y="-20" width="16" height="40"/>
</clipPath>
<clipPath id="speedClip">
<rect x="8" y="-20" width="17" height="40"/>
</clipPath>
<!-- ========================================== -->
<!-- Two gradients, one with no values defined -->
<!-- and one with the default values specified -->
<!-- They should create the same pattern -->
<!-- ========================================== -->
<linearGradient id="lgDefaults" spreadMethod="repeat">
<stop offset=".0" stop-color="gold" />
<stop offset=".49" stop-color="crimson" />
<stop offset=".51" stop-color="gold" />
<stop offset="1." stop-color="crimson" />
</linearGradient>
<linearGradient id="lgUR" xlink:href="#lgDefaults"
x1="25%" x2="75%" y1="75%" y2="25%"/>
<linearGradient id="lgU" xlink:href="#lgDefaults"
x1="25%" x2="25%" y1="75%" y2="25%"/>
<linearGradient id="lgUL" xlink:href="#lgDefaults"
x1="75%" x2="25%" y1="75%" y2="25%"/>
<linearGradient id="lgL" xlink:href="#lgDefaults"
x1="75%" x2="25%" y1="25%" y2="25%"/>
<linearGradient id="lgDL" xlink:href="#lgDefaults"
x1="75%" x2="25%" y1="25%" y2="75%"/>
<linearGradient id="lgD" xlink:href="#lgDefaults"
x1="25%" x2="25%" y1="25%" y2="75%"/>
<linearGradient id="lgDR" xlink:href="#lgDefaults"
x1="25%" x2="75%" y1="25%" y2="75%"/>
<linearGradient id="lgR" xlink:href="#lgDefaults"
x1="25%" x2="75%" y1="25%" y2="25%"/>
</defs>
<g transform="translate(70, 110) scale(2)" font-size="8">
<g transform="translate(0, 0)" text-anchor="middle">
<g transform="translate(0, 0)">
<use xlink:href="#testShape" fill="url(#lgR)" />
<text y="-23">Right</text>
</g>
<g transform="translate(0, 55)">
<use xlink:href="#testShape" fill="url(#lgUR)" />
<text y="-23">Up Right</text>
</g>
<g transform="translate(0, 110)">
<use xlink:href="#testShape" fill="url(#lgU)" />
<text y="-23">Up</text>
</g>
<g transform="translate(0, 165)">
<use xlink:href="#testShape" fill="url(#lgUL)" />
<text y="-23">Up Left</text>
</g>
</g>
<g transform="translate(70, 0)" text-anchor="middle">
<g transform="translate(0, 0)">
<use xlink:href="#testShape" fill="url(#lgL)" />
<text y="-23">Left</text>
</g>
<g transform="translate(0, 55)">
<use xlink:href="#testShape" fill="url(#lgDL)" />
<text y="-23">Down Left</text>
</g>
<g transform="translate(0, 110)">
<use xlink:href="#testShape" fill="url(#lgD)" />
<text y="-23">Down</text>
</g>
<g transform="translate(0, 165)">
<use xlink:href="#testShape" fill="url(#lgDR)" />
<text y="-23">Down Right</text>
</g>
</g>
</g>
</svg>
1.8 +47 -5 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.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- LinearGradientPaintContext.java 13 Sep 2001 21:55:52 -0000 1.7
+++ LinearGradientPaintContext.java 10 Dec 2002 16:19:17 -0000 1.8
@@ -30,8 +30,13 @@
* a device space coordinate, (X, Y):
* g(X, Y) = dgdX*X + dgdY*Y + gc
*/
- private float dgdX, dgdY, gc;
+ private float dgdX, dgdY, gc, pixSz;
+ private static final int DEFAULT_IMPL = 1;
+ private static final int ANTI_ALIAS_IMPL = 3;
+
+ private int fillMethod;
+
/**
* Constructor for LinearGradientPaintContext.
*
@@ -106,11 +111,34 @@
float constX = dx/dSq;
float constY = dy/dSq;
- dgdX = a00*constX + a10*constY;//incremental change along gradient for +x
- dgdY = a01*constX + a11*constY;//incremental change along gradient for +y
+ //incremental change along gradient for +x
+ dgdX = a00*constX + a10*constY;
+ //incremental change along gradient for +y
+ dgdY = a01*constX + a11*constY;
+
+ float dgdXAbs = Math.abs(dgdX);
+ float dgdYAbs = Math.abs(dgdY);
+ if (dgdXAbs > dgdYAbs) pixSz = dgdXAbs;
+ else pixSz = dgdYAbs;
//constant, incorporates the translation components from the matrix
gc = (a02-start.x)*constX + (a12-start.y)*constY;
+
+ Object colorRend = hints.get(RenderingHints.KEY_COLOR_RENDERING);
+ Object rend = hints.get(RenderingHints.KEY_RENDERING);
+
+ fillMethod = DEFAULT_IMPL;
+
+ if ((cycleMethod == MultipleGradientPaint.REPEAT) ||
+ hasDiscontinuity) {
+ if (rend == RenderingHints.VALUE_RENDER_QUALITY)
+ fillMethod = ANTI_ALIAS_IMPL;
+ // ColorRend overrides rend.
+ if (colorRend == RenderingHints.VALUE_COLOR_RENDER_SPEED)
+ fillMethod = DEFAULT_IMPL;
+ else if (colorRend == RenderingHints.VALUE_COLOR_RENDER_QUALITY)
+ fillMethod = ANTI_ALIAS_IMPL;
+ }
}
protected void fillHardNoCycle(int[] pixels, int off, int adjust,
@@ -448,7 +476,21 @@
//constant which can be pulled out of the inner loop
final float initConst = (dgdX*x) + gc;
- if (!isSimpleLookup) {
+ if (fillMethod == ANTI_ALIAS_IMPL) {
+ //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++] = indexGradientAntiAlias(g, pixSz);
+ g += dgdX; //incremental change in g
+ }
+ off += adjust; //change in off from row to row
+ }
+ }
+ else if (!isSimpleLookup) {
if (cycleMethod == MultipleGradientPaint.NO_CYCLE) {
fillHardNoCycle(pixels, off, adjust, x, y, w, h);
}
1.13 +2 -2 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.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- MultipleGradientPaintContext.java 11 Mar 2002 16:49:22 -0000 1.12
+++ MultipleGradientPaintContext.java 10 Dec 2002 16:19:17 -0000 1.13
@@ -888,7 +888,7 @@
// p1 and p2 my pass each other which will cause no end of
// trouble.
sz -= intSz;
- weight = (1-sz)/(intSz+sz);
+ weight = 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
1.7 +187 -47 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.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- RadialGradientPaintContext.java 13 Sep 2001 21:55:52 -0000 1.6
+++ RadialGradientPaintContext.java 10 Dec 2002 16:19:17 -0000 1.7
@@ -508,53 +508,195 @@
final double constC =
-(radiusSq) + (centerX * centerX) + (centerY * centerY);
//coefficients of the quadratic equation (Ax^2 + Bx + C = 0)
- double A, B, C;
- double slope; //slope of the focus-perimeter line
- double yintcpt; //y-intercept of the focus-perimeter line
- double solutionX;//intersection with circle X coordinate
- double solutionY;//intersection with circle Y coordinate
- final float constX = (a00*x) + (a01*y) + a02;//const part of X coord
- final float constY = (a10*x) + (a11*y) + a12; //const part of Y coord
final float precalc2 = 2 * centerY;//const in inner loop quad. formula
final float precalc3 =-2 * centerX;//const in inner loop quad. formula
- float det; //determinant of quadratic formula (should always be >0)
+ //const part of X,Y coord (shifted to bottom left corner of pixel.
+ final float constX = (a00*(x-.5f)) + (a01*(y+.5f)) + a02;
+ final float constY = (a10*(x-.5f)) + (a11*(y+.5f)) + a12;
float X; // User space point X coordinate
float Y; // User space point Y coordinate
- float g;//value specifying position in the gradient
- float delta; // range around g to average for anti-aliasing
-
- float currentToFocusSq;//sq distance from the current pt. to focus
- float intersectToFocusSq;//sq distance from the intersect pt. to focus
- float deltaXSq; //temp variable for a change in X squared.
- float deltaYSq; //temp variable for a change in Y squared.
-
- int j, end; //indexing variables for FOR loops
- int indexer = off; //index variable for pixels array
+ int i, j; //indexing variables for FOR loops
+ int indexer = off-1; //index variable for pixels array
// Size of a pixel in user space.
- float pixSzSq = (float)(a00*a00+a01*a01+a10*a10+a11*a11);
-
+ double pixSzSq = (float)(a00*a00+a01*a01+a10*a10+a11*a11);
+ double [] prevGs = new double[w+1];
+ double deltaXSq, deltaYSq;
+ double solutionX, solutionY;
+ double slope, yintcpt, A, B, C, det;
+ double intersectToFocusSq, currentToFocusSq;
+ double g00, g01, g10, g11;
+
+ // Set X,Y to top left corner of first pixel of first row.
+ X = constX - a01;
+ Y = constY - a11;
+
+ // Calc top row of g's.
+ for (i=0; i <= w; i++) {
+ // special case to avoid divide by zero or very near zero
+ if (((X-focusX)>-0.000001) &&
+ ((X-focusX)< 0.000001)) {
+ solutionX = focusX;
+ solutionY = centerY;
+ solutionY += (Y > focusY)?trivial:-trivial;
+ }
+ else {
+ // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
+ // Formula line: Y = Slope*x + Y0;
+ //
+ // So you substitue line into Circle and apply
+ // Quadradic formula.
+
+
+ //slope of the focus-current line
+ slope = (Y - focusY) / (X - focusX);
+
+ yintcpt = Y - (slope * X); //y-intercept of that same line
+
+ //use the quadratic formula to calculate the intersection
+ //point
+ A = (slope * slope) + 1;
+
+ B = precalc3 + (-2 * slope * (centerY - yintcpt));
+
+ C = constC + (yintcpt* (yintcpt - precalc2));
+
+ det = Math.sqrt((B * B) - ( 4 * A * C));
+
+ solutionX = -B;
+
+ //choose the positive or negative root depending
+ //on where the X coord lies with respect to the focus.
+ solutionX += (X < focusX)?-det:det;
+
+ solutionX = solutionX / (2 * A);//divisor
+
+ solutionY = (slope * solutionX) + yintcpt;
+ }
+
+ //calculate the square of the distance from the current point
+ //to the focus and the square of the distance from the
+ //intersection point to the focus. Want the squares so we can
+ //do 1 square root after division instead of 2 before.
+ deltaXSq = solutionX - focusX;
+ deltaXSq = deltaXSq * deltaXSq;
+
+ deltaYSq = solutionY - focusY;
+ deltaYSq = deltaYSq * deltaYSq;
+
+ intersectToFocusSq = deltaXSq + deltaYSq;
+
+ deltaXSq = X - focusX;
+ deltaXSq = deltaXSq * deltaXSq;
+
+ deltaYSq = Y - focusY;
+ deltaYSq = deltaYSq * deltaYSq;
+
+ currentToFocusSq = deltaXSq + deltaYSq;
+
+ //want the percentage (0-1) of the current point along the
+ //focus-circumference line
+ prevGs[i] = Math.sqrt(currentToFocusSq / intersectToFocusSq);
+
+ X += a00; //incremental change in X, Y
+ Y += a10;
+ }
+
for (j = 0; j < h; j++) { //for every row
- X = (a01*j) + constX; //constants from column to column
+ // Set X,Y to bottom edge of pixel row.
+ X = (a01*j) + constX; //constants from row to row
Y = (a11*j) + constY;
-
+
+ g10 = prevGs[0];
+ // special case to avoid divide by zero or very near zero
+ if (((X-focusX)>-0.000001) &&
+ ((X-focusX)< 0.000001)) {
+ solutionX = focusX;
+ solutionY = centerY;
+ solutionY += (Y > focusY)?trivial:-trivial;
+ }
+ else {
+ // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
+ // Formula line: Y = Slope*x + Y0;
+ //
+ // So you substitue line into Circle and apply
+ // Quadradic formula.
+
+
+ //slope of the focus-current line
+ slope = (Y - focusY) / (X - focusX);
+
+ yintcpt = Y - (slope * X); //y-intercept of that same line
+
+ //use the quadratic formula to calculate the intersection
+ //point
+ A = (slope * slope) + 1;
+
+ B = precalc3 + (-2 * slope * (centerY - yintcpt));
+
+ C = constC + (yintcpt* (yintcpt - precalc2));
+
+ det = Math.sqrt((B * B) - ( 4 * A * C));
+
+ solutionX = -B;
+
+ //choose the positive or negative root depending
+ //on where the X coord lies with respect to the focus.
+ solutionX += (X < focusX)?-det:det;
+
+ solutionX = solutionX / (2 * A);//divisor
+
+ solutionY = (slope * solutionX) + yintcpt;
+ }
+
+ //calculate the square of the distance from the current point
+ //to the focus and the square of the distance from the
+ //intersection point to the focus. Want the squares so we can
+ //do 1 square root after division instead of 2 before.
+ deltaXSq = solutionX - focusX;
+ deltaXSq = deltaXSq * deltaXSq;
+
+ deltaYSq = solutionY - focusY;
+ deltaYSq = deltaYSq * deltaYSq;
+
+ intersectToFocusSq = deltaXSq + deltaYSq;
+
+ deltaXSq = X - focusX;
+ deltaXSq = deltaXSq * deltaXSq;
+
+ deltaYSq = Y - focusY;
+ deltaYSq = deltaYSq * deltaYSq;
+
+ currentToFocusSq = deltaXSq + deltaYSq;
+ g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
+ prevGs[0] = g11;
+
+ X += a00; //incremental change in X, Y
+ Y += a10;
+
//for every column (inner loop begins here)
- for (end = indexer + w; indexer < end; indexer++) {
-
+ for (i=1; i <= w; i++) {
+ g00 = g10;
+ g01 = g11;
+ g10 = prevGs[i];
+
// special case to avoid divide by zero or very near zero
if (((X-focusX)>-0.000001) &&
((X-focusX)< 0.000001)) {
solutionX = focusX;
-
solutionY = centerY;
-
solutionY += (Y > focusY)?trivial:-trivial;
}
-
- else {
-
+ else {
+ // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
+ // Formula line: Y = Slope*x + Y0;
+ //
+ // So you substitue line into Circle and apply
+ // Quadradic formula.
+
+
//slope of the focus-current line
slope = (Y - focusY) / (X - focusX);
@@ -568,7 +710,7 @@
C = constC + (yintcpt* (yintcpt - precalc2));
- det = (float)Math.sqrt((B * B) - ( 4 * A * C));
+ det = Math.sqrt((B * B) - ( 4 * A * C));
solutionX = -B;
@@ -585,36 +727,34 @@
//to the focus and the square of the distance from the
//intersection point to the focus. Want the squares so we can
//do 1 square root after division instead of 2 before.
-
- deltaXSq = (float)solutionX - focusX;
+ deltaXSq = solutionX - focusX;
deltaXSq = deltaXSq * deltaXSq;
-
- deltaYSq = (float)solutionY - focusY;
+
+ deltaYSq = solutionY - focusY;
deltaYSq = deltaYSq * deltaYSq;
-
+
intersectToFocusSq = deltaXSq + deltaYSq;
-
+
deltaXSq = X - focusX;
deltaXSq = deltaXSq * deltaXSq;
-
+
deltaYSq = Y - focusY;
deltaYSq = deltaYSq * deltaYSq;
-
+
currentToFocusSq = deltaXSq + deltaYSq;
-
- //want the percentage (0-1) of the current point along the
- //focus-circumference line
- g = (float)Math.sqrt(currentToFocusSq / intersectToFocusSq);
+ g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
+ prevGs[i] = g11;
//Get the color at this point
- delta = (float)Math.sqrt(pixSzSq/intersectToFocusSq);
- pixels[indexer] = indexGradientAntiAlias(g, delta);
-
+ pixels[indexer+i] = indexGradientAntiAlias
+ ((float)((g00+g01+g10+g11)/4),
+ (float)Math.max(Math.abs(g11-g00),
+ Math.abs(g10-g01)));
+
X += a00; //incremental change in X, Y
Y += a10;
} //end inner loop
- indexer += adjust;
+ indexer += (w+adjust);
} //end outer loop
}
-
}
1.89 +2 -1 xml-batik/test-resources/org/apache/batik/test/samplesRendering.xml
Index: samplesRendering.xml
===================================================================
RCS file: /home/cvs/xml-batik/test-resources/org/apache/batik/test/samplesRendering.xml,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -r1.88 -r1.89
--- samplesRendering.xml 25 Nov 2002 16:14:15 -0000 1.88
+++ samplesRendering.xml 10 Dec 2002 16:19:17 -0000 1.89
@@ -187,6 +187,7 @@
<test id="samples/tests/spec/paints/gradientLimit.svg" />
<test id="samples/tests/spec/paints/linearGradientOrientation.svg" />
<test id="samples/tests/spec/paints/linearGradientLine.svg" />
+ <test id="samples/tests/spec/paints/linearGradientRepeat.svg" />
<test id="samples/tests/spec/paints/radialGradientLine.svg" />
<test id="samples/tests/spec/paints/gradientPoint.svg" />
<test id="samples/tests/spec/paints/patternPreserveAspectRatioA.svg" />
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org