You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by de...@apache.org on 2006/04/21 13:00:09 UTC
svn commit: r395847 - in /xmlgraphics/batik/branches/svg11: samples/
sources/org/apache/batik/apps/rasterizer/
sources/org/apache/batik/ext/awt/image/rendered/
sources/org/apache/batik/gvt/event/ sources/org/apache/batik/swing/gvt/
sources/org/apache/b...
Author: deweese
Date: Fri Apr 21 04:00:05 2006
New Revision: 395847
URL: http://svn.apache.org/viewcvs?rev=395847&view=rev
Log:
1) Applied patch from 35683 (Thanks Dieter)
2) Applied patch from 39297 (modified for SVG11 branch) - (Thanks Dieter)
3) Applied suggestion from 39058 (Thanks Chris)
4) Fixed problem with ZoomAndPan handling overriding user disabling of
Interactors.
5) More sensible handling of source 'URLs' in svgrasterizer.
Modified:
xmlgraphics/batik/branches/svg11/samples/batikLogo.svg
xmlgraphics/batik/branches/svg11/sources/org/apache/batik/apps/rasterizer/SVGConverterURLSource.java
xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java
xmlgraphics/batik/branches/svg11/sources/org/apache/batik/gvt/event/AWTEventDispatcher.java
xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/gvt/TextSelectionManager.java
xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/svg/JSVGComponent.java
xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/print/PrintTranscoder.java
Modified: xmlgraphics/batik/branches/svg11/samples/batikLogo.svg
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/samples/batikLogo.svg?rev=395847&r1=395846&r2=395847&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/samples/batikLogo.svg (original)
+++ xmlgraphics/batik/branches/svg11/samples/batikLogo.svg Fri Apr 21 04:00:05 2006
@@ -28,9 +28,18 @@
<!-- @version $Id$ -->
<!-- ====================================================================== -->
-<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">
+<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"
+ onload="load()">
<title>Batik Logo</title>
<g id="content">
+ <script type="text/ecmascript"><![CDATA[
+ function load() {
+ var e = document.getElementById("Batik_Logo_Underline2");
+ System.err.println("Elem: " + e);
+ e.setAttributeNS(null, "style",
+ "fill:url(file:///C:/de.svg#MyGradient)");
+ }
+ ]]></script>
<defs>
<symbol id="Batik_Squiggle" stroke="none" viewBox="0 0 540 570">
<path id="Batik_Squiggle_Blue" fill="#6666FF"
@@ -137,7 +146,7 @@
<hkern g1="ti" g2="k" k="6"/>
</font>
- <g id="Batik_Logo_Underline" transform="scale(.75,.75)" >
+ <g id="Batik_Logo_Underline" transform="scale(.75,.75)">
<path d="M37.886,60c-0.018,0.1-0.377,1.375-0.439,1.492c-0.15,0.285-1.382,2.046-1.598,2.291c0.206-0.233,0.428-0.452,0.65-0.67c-6.851,6.751-0.262,0.713,0.893-0.499c1.893-1.986-2.124,1.712,0.112-0.08
c0.604-0.484,1.242-0.925,1.886-1.355c-2.574,1.719,0.458-0.228,1.417-0.868c-2.634,1.761-1.231,0.788-0.605,0.423c1.799-1.049,3.686-1.946,5.591-2.783c0.978-0.43,1.97-0.828,2.964-1.217c1.844-0.723-1.918,0.683-0.003,0.012
c0.706-0.264,1.412-0.528,2.117-0.792c-1.224,0.456-1.388,0.521-0.491,0.195c2.531-0.908,5.102-1.708,7.683-2.461c5.73-1.672,11.556-3.013,17.401-4.216c30.689-6.315,61.555-8.765,92.723-10.467c35.225-1.924,70.559-2.313,105.819-1.278
@@ -176,6 +185,19 @@
</defs>
<use x="65" y="233" xlink:href="#Batik_Logo_Shadow" />
+
+
+ <g id="Batik_Logo_Underline2" transform="scale(.75,.75)">
+ <path d="M37.886,60c-0.018,0.1-0.377,1.375-0.439,1.492c-0.15,0.285-1.382,2.046-1.598,2.291c0.206-0.233,0.428-0.452,0.65-0.67c-6.851,6.751-0.262,0.713,0.893-0.499c1.893-1.986-2.124,1.712,0.112-0.08
+ c0.604-0.484,1.242-0.925,1.886-1.355c-2.574,1.719,0.458-0.228,1.417-0.868c-2.634,1.761-1.231,0.788-0.605,0.423c1.799-1.049,3.686-1.946,5.591-2.783c0.978-0.43,1.97-0.828,2.964-1.217c1.844-0.723-1.918,0.683-0.003,0.012
+ c0.706-0.264,1.412-0.528,2.117-0.792c-1.224,0.456-1.388,0.521-0.491,0.195c2.531-0.908,5.102-1.708,7.683-2.461c5.73-1.672,11.556-3.013,17.401-4.216c30.689-6.315,61.555-8.765,92.723-10.467c35.225-1.924,70.559-2.313,105.819-1.278
+ c27.375,0.803,55.137,2.029,82.154,6.813c1.854,0.328,3.702,0.69,5.545,1.079c-2.182-0.459,0.632,0.149,1.102,0.26c0.785,0.185,1.566,0.383,2.347,0.585c2.714,0.705,5.407,1.537,7.987,2.642c0.676-4.98,1.351-9.959,2.026-14.939
+ c-29.001,20.428-70.184,18.783-104.484,20.881c-37.85,2.314-78.422,7.341-105.371,37.024c-3.142,3.46-5.693,10.35-0.21,12.998c8.018,3.873,16.683,5.137,25.266,7.166c7.149,1.69,13.362,4.381,16.934,11.121c4.934,9.311,2.75,18.519-0.175,28.003
+ c-3.217,10.428-5.508,20.886-0.692,31.219c4.219,9.05,19.441-3.641,15.823-11.611c-4.234-9.326,1.407-19.828,3.653-28.997c2.667-10.888,1.908-22.401-3.872-32.224c-9.76-16.588-31.066-13.848-46.449-21.271c-0.07,4.333-0.14,8.666-0.21,12.998
+ c10.537-11.719,25.017-18.668,40.974-22.714c18.159-4.604,37.034-5.719,55.666-6.747c37.146-2.049,77.822-2.405,109.506-24.634c4.136-2.902,8.771-12.048,2.026-14.939c-7.868-3.373-16.687-4.781-25.083-6.132c-12.447-2.004-25.032-3.156-37.6-4.075
+ c-33.215-2.427-66.599-2.839-99.887-2.247c-34.872,0.621-69.791,2.496-104.432,6.637c-24.317,2.907-50.972,6.112-73.187,17.171c-4.951,2.465-9.505,5.587-13.309,9.623c-1.027,1.089-2.19,2.464-2.986,3.643c0.137-0.203-3.419,6.639-1.518,3.165
+ c-0.205,0.374-0.38,0.762-0.549,1.151c-1.126,2.59-2.056,5.322-2.196,8.168c-0.222,4.484,4.48,3.091,6.917,1.551c3.856-2.437,7.345-6.516,8.167-11.093z"/>
+ </g> <!-- End Batik_Logo_Underline -->
</g>
<!-- ============================================================= -->
Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/apps/rasterizer/SVGConverterURLSource.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/apps/rasterizer/SVGConverterURLSource.java?rev=395847&r1=395846&r2=395847&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/apps/rasterizer/SVGConverterURLSource.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/apps/rasterizer/SVGConverterURLSource.java Fri Apr 21 04:00:05 2006
@@ -52,29 +52,40 @@
// Get the path portion
String path = this.purl.getPath();
- if (path == null ||
- !(path.toLowerCase().endsWith(SVG_EXTENSION) ||
- path.toLowerCase().endsWith(SVGZ_EXTENSION))){
- throw new SVGConverterException(ERROR_INVALID_URL,
- new Object[]{url});
- }
-
- int n = path.lastIndexOf("/");
+ int n = path.lastIndexOf('/');
+ String file = path;
if (n != -1){
// The following is safe because we know there is at least ".svg"
// after the slash.
- path = path.substring(n+1);
+ file = path.substring(n+1);
+ }
+ if (file.length() == 0) {
+ int idx = path.lastIndexOf('/', n-1);
+ file = path.substring(idx+1, n);
+ }
+ if (file.length() == 0) {
+ throw new SVGConverterException(ERROR_INVALID_URL,
+ new Object[]{url});
+ }
+ n = file.indexOf('?');
+ String args = "";
+ if (n != -1) {
+ args = file.substring(n+1);
+ file = file.substring(0, n);
}
-
- name = path;
+
+ name = file;
//
// The following will force creation of different output file names
// for urls with references (e.g., anne.svg#svgView(viewBox(0,0,4,5)))
//
String ref = this.purl.getRef();
- if (ref != null && (ref.length()!=0)) {
- name += "" + ref.hashCode();
+ if ((ref != null) && (ref.length()!=0)) {
+ name += "_" + ref.hashCode();
+ }
+ if ((args != null) && (args.length()!=0)) {
+ name += "_" + args.hashCode();
}
}
Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java?rev=395847&r1=395846&r2=395847&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java Fri Apr 21 04:00:05 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2002-2003 The Apache Software Foundation
+ Copyright 2002-2003,2006 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -29,49 +29,94 @@
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.util.Iterator;
-import java.util.Vector;
+import java.util.List;
+import java.util.ArrayList;
import org.apache.batik.ext.awt.image.GraphicsUtil;
/**
- * This implements an adaptive pallete generator to reduce images to a
+ * This class implements an adaptive palette generator to reduce images to a
* specified number of colors.
*
* Ideally this would also support a better dither option than just
* the JDK's pattern dither.
*
+ * The algorithm used is the 'Median Cut Algorithm' published by
+ * Paul Heckbert in early '80s.
+ *
* @author <a href="mailto:deweese@apache.org">Thomas DeWeese</a>
* @author <a href="mailto:jun@oop-reserch.com">Jun Inamori</a>
- * @version $Id$ */
+ * @version $Id$
+ */
+
public class IndexImage{
/**
* Used to track a color and the number of pixels of that colors
*/
private static class Counter {
- public int val;
- public int count=1;
- public Counter(int val) { this.val = val; }
- public boolean add(int val) {
+
+ /**
+ * contains the 'packed' rgb-color for this point.
+ * Must not change after construction!
+ */
+ final int val;
+
+ /**
+ * the number of image-pixels with this color.
+ */
+ int count=1;
+
+ Counter(int val) { this.val = val; }
+
+ boolean add(int val) {
// See if the value matches us...
if (this.val != val)
return false;
count++;
return true;
}
- }
+
+ /**
+ * convert the color-point of this counter to an rgb-array.
+ * To avoid creating lots of arrays, the caller passes the
+ * array to store the result.
+ *
+ * @param rgb an int[ 3 ] to store the result.
+ * @return an int-array with rgb-color-values (same as rgb-parameter)
+ */
+ int[] getRgb( int[] rgb ){
+ rgb[ Cube.RED ] = (val&0xFF0000)>>16;
+ rgb[ Cube.GRN ] = (val&0x00FF00)>>8;
+ rgb[ Cube.BLU ] = (val&0x0000FF);
+ return rgb;
+ }
+ }
/**
* Used to define a cube of the colorspace. The cube can be split
- * approximagely in half to generate two cubes.
+ * approximagely in half to generate two cubes.
*/
private static class Cube {
- int []min={0, 0, 0}, max={255,255,255};
+ static final byte[] RGB_BLACK= new byte[]{ 0, 0, 0 };
+
+ int[] min = {0, 0, 0}, max={255,255,255};
boolean done = false;
- Vector []colors = null;
+
+ /**
+ * the colors-array is not modified - in fact, all cubes use
+ * the same colors-array. The Counter contains the
+ * rgb-color-code and the count of pixels with this color.
+ */
+ final Counter[][] colors;
+
+ /**
+ * the number of color-points in this cube.
+ */
int count=0;
+
static final int RED = 0;
static final int GRN = 1;
static final int BLU = 2;
@@ -81,7 +126,7 @@
* @param colors contains the 3D color histogram to be subdivided
* @param count the total number of pixels in the 3D histogram.
*/
- public Cube(Vector []colors, int count) {
+ Cube( Counter[][] colors, int count) {
this.colors = colors;
this.count = count;
}
@@ -91,122 +136,193 @@
* further
*/
public boolean isDone() { return done; }
+
+ /**
+ * check, if the color defined by val[] is inside this cube.
+ *
+ * @param val int[ 3 ] containing r,g,b-values
+ * @return true when color is inside this cube
+ */
+ private boolean contains( int[] val ){
+
+ int vRed = val[ RED ]; // just save some array-accesses
+ int vGrn = val[ GRN ];
+ int vBlu = val[ BLU ];
+
+ return (
+ ( ( min[ RED ] <= vRed ) && ( vRed <= max[ RED ]))&&
+ ( ( min[ GRN ] <= vGrn ) && ( vGrn <= max[ GRN ]))&&
+ ( ( min[ BLU ] <= vBlu ) && ( vBlu <= max[ BLU ])));
+ }
+
/**
* Splits the cube into two parts. This cube is
* changed to be one half and the returned cube is the other half.
* This tries to pick the right channel to split on.
*/
- public Cube split() {
- int dr = max[0]-min[0]+1;
- int dg = max[1]-min[1]+1;
- int db = max[2]-min[2]+1;
+ Cube split() {
+ int dr = max[ RED ]-min[ RED ]+1;
+ int dg = max[ GRN ]-min[ GRN ]+1;
+ int db = max[ BLU ]-min[ BLU ]+1;
int c0, c1, splitChannel;
// Figure out which axis is the longest and split along
// that axis (this tries to keep cubes square-ish).
if (dr >= dg) {
- c0 = GRN;
- if (dr >= db) { splitChannel = RED; c1=BLU; }
- else { splitChannel = BLU; c1=RED; }
+ if (dr >= db) { splitChannel = RED; c0=GRN; c1=BLU; }
+ else { splitChannel = BLU; c0=RED; c1=GRN; }
} else if (dg >= db) {
splitChannel = GRN;
c0=RED;
c1=BLU;
} else {
splitChannel = BLU;
- c0=RED;
- c1=GRN;
+ c0=GRN;
+ c1=RED;
}
+// System.out.println("Red:" + dr
+// + " Grn:" + dg
+// + " Blu:" + db
+// + " Split:" + splitChannel
+// + " c0:" + c0
+// + " c1:" + c1 );
+
Cube ret;
+
+ // try to split the longest axis
ret = splitChannel(splitChannel, c0, c1);
if (ret != null ) return ret;
+ // try to split along the 2nd longest axis
ret = splitChannel(c0, splitChannel, c1);
if (ret != null ) return ret;
+ // only one left
ret = splitChannel(c1, splitChannel, c0);
if (ret != null) return ret;
-
+
+ // so far, no split was possible trying all 3 colors: this
+ // cube can't be split further
done = true;
return null;
}
/**
+ * Adjust (normalize) min/max of this cube so that they span
+ * the actual content. This method is called on the two cubes
+ * resulting from a split. <br> We search the counts[] from
+ * min to max for the leftmost non-null entry. That is the
+ * new min. Then we search counts[] from max to min for the
+ * rightmost non-null entry. That is the new max. <br>This
+ * requires, that {@link #computeCounts } really computes
+ * <i>all</i> counts-values (and does not stop after the
+ * necessary number of points for a split is found, as it was
+ * done in the previous version of this class).
+ *
+ * @param splitChannel the color used for the last split
+ * @param counts contains the number of points along the splitChannel
+ * - only counts[ min .. max ] is valid.
+ */
+ private void normalize( int splitChannel, int[] counts ){
+
+ if ( count == 0 ){
+ // empty cube: nothing to normalize
+ return;
+ }
+
+ int iMin = min[ splitChannel ];
+ int iMax = max[ splitChannel ];
+ int loBound = -1;
+ int hiBound = -1;
+
+ // we search from left to right for the first non-null
+ // entry in counts[]
+ for( int i = iMin; i <= iMax; i++ ){
+ if ( counts[ i ] == 0 ){
+ // this entry is 0: search more
+ continue;
+ }
+
+ // we reached a non-null entry: stop looking further
+ loBound = i;
+ break;
+ }
+
+ // we search from right to left for the first non-null
+ // entry in counts[]
+ for( int i= iMax; i >= iMin; i-- ){
+ if ( counts[ i ] == 0 ){
+ // this entry is 0: search more
+ continue;
+ }
+ // we reached a non-null entry: stop looking further
+ hiBound = i;
+ break;
+ }
+
+ boolean flagChangedLo = (loBound != -1 ) && ( iMin != loBound );
+ boolean flagChangedHi = (hiBound != -1 ) && ( iMax != hiBound );
+// if ( flagChangedLo || flagChangedHi ){
+// System.out.println("old min:" + min[ splitChannel ] + "/max:" + max[ splitChannel ]
+// + " new: " + loBound + "/" + hiBound );
+// StringBuffer buff = new StringBuffer( 100 );
+// for( int i= min[ splitChannel ]; i <= max[ splitChannel]; i++ ){
+// buff.append( counts[ i ] );
+// buff.append( ',' );
+// }
+// System.out.println("Counts:" + buff );
+// }
+
+ if ( flagChangedLo ){
+ min[ splitChannel ]= loBound;
+ }
+ if ( flagChangedHi ){
+ max[ splitChannel ]= hiBound;
+ }
+ }
+
+
+ /**
* Splits the image according to the parameters. It tries
* to find a location where half the pixels are on one side
* and half the pixels are on the other.
*/
- public Cube splitChannel(int splitChannel, int c0, int c1) {
- if (min[splitChannel] == max[splitChannel]) return null;
-
- int splitSh4 = (2-splitChannel)*4;
- int c0Sh4 = (2-c0)*4;
- int c1Sh4 = (2-c1)*4;
+ Cube splitChannel(int splitChannel, int c0, int c1) {
+
+ if (min[splitChannel] == max[splitChannel]) {
+ // thickness along the splitChannel is only one point: cannot split
+ return null;
+ }
+
+ if ( count == 0 ){
+ // this Cube has no points: cannot split
+ return null;
+ }
+
+ // System.out.println( toString() );
int half = count/2;
// Each entry is the number of pixels that have that value
// in the split channel within the cube (so pixels
// that have that value in the split channel aren't counted
// if they are outside the cube in the other color channels.
- int counts [] = new int[256];
- int tcount = 0;
-
- // System.out.println("Cube: [" +
- // min[0] + "-" + max[0] + "] [" +
- // min[1] + "-" + max[1] + "] [" +
- // min[2] + "-" + max[2] + "]");
+ int[] counts = computeCounts( splitChannel, c0, c1 );
- int [] minIdx = {min[0]>>4, min[1]>>4, min[2]>>4};
- int [] maxIdx = {max[0]>>4, max[1]>>4, max[2]>>4};
- int minR=min[0], minG=min[1], minB=min[2];
- int maxR=max[0], maxG=max[1], maxB=max[2];
- int val = 0;
- int [] vals = {0, 0, 0};
- for (int i=minIdx[splitChannel]; i<=maxIdx[splitChannel]; i++) {
- int idx1 = i<<splitSh4;
- for (int j=minIdx[c0]; j<=maxIdx[c0]; j++) {
- int idx2 = idx1 | (j<<c0Sh4);
- for (int k=minIdx[c1]; k<=maxIdx[c1]; k++) {
- int idx = idx2 | (k<<c1Sh4);
- Vector v = colors[idx];
- if (v==null) continue;
- Iterator itr = v.iterator();
- Counter c;
- while (itr.hasNext()) {
- c = (Counter)itr.next();
- val = c.val;
- vals[0] = (val&0xFF0000)>>16;
- vals[1] = (val&0xFF00)>>8;
- vals[2] = (val&0xFF);
- if (((vals[0] >= minR) && (vals[0] <= maxR))&&
- ((vals[1] >= minG) && (vals[1] <= maxG))&&
- ((vals[2] >= minB) && (vals[2] <= maxB))) {
- // The val lies within this cube so count it.
- counts[vals[splitChannel]] += c.count;
- tcount += c.count;
- }
- }
- }
- }
- // We've found the half way point. Note that the
- // rest of counts is not filled out.
- if (tcount >= half) break;
- }
-
- tcount=0;
+ int tcount=0;
int lastAdd=-1;
// These indicate what the top value for the low cube and
// the low value of the high cube should be in the split channel
// (they may not be one off if there are 'dead' spots in the
// counts array.
- int splitLo=min[splitChannel], splitHi=max[splitChannel];
+ int splitLo=min[splitChannel];
+ int splitHi=max[splitChannel];
for (int i=min[splitChannel]; i<=max[splitChannel]; i++) {
int c = counts[i];
if (c == 0) {
// No counts below this so move up bottom of cube.
if ((tcount == 0) && (i < max[splitChannel]))
- this.min[splitChannel] = i+1;
+ min[splitChannel] = i+1;
continue;
}
@@ -219,24 +335,25 @@
// Then lastAdd is a better top idx for this then i.
if (lastAdd == -1) {
// No lower place to break.
- if (c == this.count) {
+ if (c == count) {
// All pixels are at this value so make min/max
// reflect that.
- this.max[splitChannel] = i;
+ max[splitChannel] = i;
return null; // no split to make.
} else {
// There are values about this one so
// split above.
splitLo = i;
splitHi = i+1;
+ tcount += c; // fix 35683
break;
}
}
splitLo = lastAdd;
splitHi = i;
} else {
- if (i == this.max[splitChannel]) {
- if ( c == this.count) {
+ if (i == max[splitChannel]) {
+ if ( c == count) {
// would move min up but that should
// have happened already.
return null; // no split to make.
@@ -256,104 +373,263 @@
break;
}
- // System.out.println("Split: " + splitChannel + "@"
- // + splitLo + "-"+splitHi +
+ // System.out.println("Split: " + splitChannel + "@"
+ // + splitLo + "-"+splitHi +
// " Count: " + tcount + " of " + count +
// " LA: " + lastAdd);
- // Create the new cube and update everone's bounds & counts.
+ // Create the new cube and update everyone's bounds & counts.
Cube ret = new Cube(colors, tcount);
- this.count = this.count-tcount;
- ret.min[splitChannel] = this.min[splitChannel];
+ count = count-tcount;
+ ret.min[splitChannel] = min[splitChannel];
ret.max[splitChannel] = splitLo;
- this.min[splitChannel] = splitHi;
- ret.min[c0] = this.min[c0];
- ret.max[c0] = this.max[c0];
- ret.min[c1] = this.min[c1];
- ret.max[c1] = this.max[c1];
+ min[splitChannel] = splitHi;
+
+ // the cube was split along splitChannel, the other
+ // dimensions dont change
+ ret.min[c0] = min[c0];
+ ret.max[c0] = max[c0];
+ ret.min[c1] = min[c1];
+ ret.max[c1] = max[c1];
+
+// if ( count <= 0 ){
+// System.out.println("This cube has no points after split:" + toString() );
+// }
+// if ( ret.count <= 0 ){
+// System.out.println("That cube has no points after split:" + ret.toString() + " this:" + toString() );
+// System.out.println("SplitLo:" + splitLo + " SplitHi:" + splitHi );
+// }
+
+ // after a split we 'normalize' both cubes, so that their
+ // min/max reflect the actual bounds of the cube. comment
+ // the next two lines when you want to see the impact of
+ // using non-normalized cubes
+ normalize( splitChannel, counts );
+ ret.normalize( splitChannel, counts );
+
return ret;
}
/**
- * Returns the average color for this cube
+ * create an array, which contains the number of pixels for
+ * each point along the splitChannel (between min and max of
+ * this cube).
+ *
+ * @param splitChannel one of RED | GRN | BLU
+ * @param c0 one of the other channels
+ * @param c1 the third channel
+ * @return an int[ 255 ] where only int[ min .. max ] contain
+ * valid counts.
+ */
+ private int[] computeCounts( int splitChannel, int c0, int c1) {
+
+ int splitSh4 = (2-splitChannel)*4;
+ int c0Sh4 = (2-c0)*4;
+ int c1Sh4 = (2-c1)*4;
+
+ // after split, each half should have half of the cube's points
+ int half = count/2;
+
+ // Each entry is the number of pixels that have that value
+ // in the split channel within the cube (so pixels
+ // that have that value in the split channel aren't counted
+ // if they are outside the cube in the other color channels.
+ int[] counts = new int[256];
+ int tcount = 0;
+
+ int minR=min[0], minG=min[1], minB=min[2];
+ int maxR=max[0], maxG=max[1], maxB=max[2];
+
+ int[] minIdx = { minR >> 4, minG >> 4, minB >> 4 };
+ int[] maxIdx = { maxR >> 4, maxG >> 4, maxB >> 4 };
+
+ int [] vals = {0, 0, 0};
+ for (int i=minIdx[splitChannel]; i<=maxIdx[splitChannel]; i++) {
+ int idx1 = i<<splitSh4;
+ for (int j=minIdx[c0]; j <=maxIdx[c0]; j++) {
+ int idx2 = idx1 | (j<<c0Sh4);
+ for (int k=minIdx[c1]; k<=maxIdx[c1]; k++) {
+ int idx = idx2 | (k<<c1Sh4);
+ Counter[] v = colors[idx];
+ for( int iColor = 0; iColor < v.length; iColor++ ){
+ Counter c = v[ iColor ];
+ vals = c.getRgb( vals );
+ if ( contains( vals )){
+ // The vals[] lies completly within
+ // this cube so count it.
+ counts[ vals[splitChannel] ] += c.count;
+ tcount += c.count;
+ }
+ }
+ }
+ }
+ // the next statement-line stops the loop after we
+ // found the split-point. however, we continue to
+ // fill the counts[] because that is needed for
+ // normalization
+// // We've found the half way point. Note that the
+// // rest of counts is not filled out.
+// if (( tcount > 0 ) && (tcount >= half)) break; // fix 35683
+ }
+
+ // the result so far is the filled counts[]
+ return counts;
+ }
+
+
+ /**
+ * convert the cube-content to String-representation for logging.
+ * @return the min/max-boundarys of the rgb-channels and
+ * pixel-count of this Cube.
+ */
+ public String toString() {
+ return "Cube: [" +
+ min[ RED ] + '-' + max[ RED ] + "] [" +
+ min[ GRN ] + '-' + max[ GRN ] + "] [" +
+ min[ BLU ] + '-' + max[ BLU ] + "] n:" + count;
+ }
+
+
+ /**
+ * Returns the average color for this cube (no alpha).
*/
public int averageColor() {
- if (this.count == 0) return 0;
+ if (count == 0) {
+ // cube is empty: return black
+ return 0;
+ }
+
+ byte[] rgb = averageColorRGB( null );
+
+ return (( rgb[ RED ] << 16 ) & 0x00FF0000)
+ | (( rgb[ GRN ] << 8 ) & 0x0000FF00)
+ | (( rgb[ BLU ] ) & 0x000000FF);
+ }
+
+ /**
+ * Returns the average color for this cube
+ */
+ public byte[] averageColorRGB( byte[] rgb ) {
+
+ if (count == 0) return RGB_BLACK;
float red=0, grn=0, blu=0;
+ // the boundarys of this cube
int minR=min[0], minG=min[1], minB=min[2];
int maxR=max[0], maxG=max[1], maxB=max[2];
int [] minIdx = {minR>>4, minG>>4, minB>>4};
int [] maxIdx = {maxR>>4, maxG>>4, maxB>>4};
- int val, ired, igrn, iblu;
- float weight;
+ int[] vals = new int[3];
+
for (int i=minIdx[0]; i<=maxIdx[0]; i++) {
int idx1 = i<<8;
for (int j=minIdx[1]; j<=maxIdx[1]; j++) {
int idx2 = idx1 | (j<<4);
for (int k=minIdx[2]; k<=maxIdx[2]; k++) {
int idx = idx2 | k;
- Vector v = colors[idx];
- if (v==null) continue;
- Iterator itr = v.iterator();
- Counter c;
- while (itr.hasNext()) {
- c = (Counter)itr.next();
- val = c.val;
- ired = (val&0xFF0000)>>16;
- igrn = (val&0x00FF00)>>8;
- iblu = (val&0x0000FF);
- if (((ired >= minR) && (ired <= maxR))&&
- ((igrn >= minG) && (igrn <= maxG))&&
- ((iblu >= minB) && (iblu <= maxB))) {
- weight = (c.count/(float)this.count);
- red += (ired*weight);
- grn += (igrn*weight);
- blu += (iblu*weight);
+ Counter[] v = colors[idx];
+ for( int iColor = 0; iColor < v.length; iColor++ ){
+ Counter c = v[ iColor ];
+ vals = c.getRgb( vals );
+ if ( contains( vals ) ) {
+ float weight = (c.count/(float)count);
+ red += (vals[0]*weight);
+ grn += (vals[1]*weight);
+ blu += (vals[2]*weight);
}
}
}
}
}
- // System.out.println("RGB: [" + red + ", " +
- // grn + ", " + blu + "]");
- return (((int)(red+0.5))<<16 |
- ((int)(grn+0.5))<<8 |
- ((int)(blu+0.5)));
+ byte[] result = (rgb == null) ? new byte[3] : rgb;
+ result[ RED ] = (byte)(red + 0.5f);
+ result[ GRN ] = (byte)(grn + 0.5f);
+ result[ BLU ] = (byte)(blu + 0.5f);
+
+ return result;
}
+
}
/**
- * Converts the input image (must be TYPE_INT_RGB or
- * TYPE_INT_ARGB) to an indexed image. Generating an adaptive
- * palette with number of colors specified.
- * @param bi the image to be processed.
- * @param nColors number of colors in the palette
+ * create an array of rgb-colors from the cubes-array.
+ * The color of each cube is computed as the sum of all colors in the cube,
+ * where each pixel is weighted according to it's count.
+ *
+ * @param nCubes number of entries to use in cubes
+ * @param cubes contains the Cubes resulting from running the split-algorithm.
+ * @return a byte[][] which is arranged as [ r|g|b ][ 0..nCubes-1 ]
*/
- static public BufferedImage getIndexedImage
- (BufferedImage bi, int nColors) {
- int w=bi.getWidth();
- int h=bi.getHeight();
+ static byte[][] computeRGB( int nCubes, Cube[] cubes ){
+
+ byte[] r = new byte[nCubes];
+ byte[] g = new byte[nCubes];
+ byte[] b = new byte[nCubes];
+
+ byte[] rgb = new byte[3];
+ for (int i=0; i<nCubes; i++) {
+ rgb = cubes[i].averageColorRGB( rgb );
+ r[i] = rgb[ Cube.RED ];
+ g[i] = rgb[ Cube.GRN ];
+ b[i] = rgb[ Cube.BLU ];
+ }
+
+ byte[][] result = new byte[3][];
+ result[ Cube.RED ] = r;
+ result[ Cube.GRN ] = g;
+ result[ Cube.BLU ] = b;
+
+// logRGB( r, g, b );
+
+ return result;
+ }
+
+ /**
+ * helper-method to print the complete rgb-arrays.
+ * @param r
+ * @param g
+ * @param b
+ */
+ static void logRGB( byte[] r, byte[] g, byte[] b ){
+
+ StringBuffer buff = new StringBuffer( 100 );
+ int nColors = r.length;
+ for( int i= 0; i < nColors; i++ ) {
+ String rgbStr= "(" + (r[i]+128) + ',' + (g[i] +128 ) + ',' + (b[i] + 128) + ")," ;
+ buff.append( rgbStr );
+ }
+ System.out.println("RGB:" + nColors + buff );
+ }
+
+
+ /**
+ * step 1: fill a data-structure with the count of each color in the image.
+ * @param bi input-image
+ * @return a List[] where each slot is a List of Counters (or null)
+ */
+ static List[] createColorList( BufferedImage bi ){
+
+ int w= bi.getWidth();
+ int h= bi.getHeight();
// Using 4 bits from RG & B.
- Vector [] colors = new Vector[1<<12];
+ List[] colors = new ArrayList[1<<12];
- int rgb=0;
for(int i_w=0; i_w<w; i_w++){
for(int i_h=0; i_h<h; i_h++){
- rgb=(bi.getRGB(i_w,i_h) & 0xFFFFFF);
+ int rgb=(bi.getRGB(i_w,i_h) & 0x00FFFFFF); // mask away alpha
// Get index from high four bits of each component.
int idx = (((rgb&0xF00000)>>> 12) |
((rgb&0x00F000)>>> 8) |
((rgb&0x0000F0)>>> 4));
- // Get the 'hash vector' for that key.
- Vector v = colors[idx];
+ // Get the 'hash vector' for that key.
+ List v = colors[idx];
if (v == null) {
- // No colors in this bin yet so create vector and
+ // No colors in this bin yet so create list and
// add color.
- v = new Vector();
+ v = new ArrayList();
v.add(new Counter(rgb));
colors[idx] = v;
} else {
@@ -372,27 +648,92 @@
}
}
+ return colors;
+ }
+
+
+ /**
+ * step 2: convert the result of step 1 to an Cube[][] which is
+ * more efficient in the following iterations. All slots in the
+ * result are filled with at least an empty array - thus we avoid
+ * tests for null. <br>Note: the converted slots in colors are no
+ * longer needed and removed.
+ *
+ * @param colors the data-structure to convert. Note that it is
+ * empty after conversion!
+ * @return same data as in colors, but Lists are converted to arrays.
+ */
+ static Counter[][] convertColorList( List[] colors ){
+
+ // used to fill empty slots
+ final Counter[] EMPTY_COUNTER = new Counter[0];
+
+ Counter[][] colorTbl= new Counter[ 1<< 12 ][];
+ for( int i= 0; i < colors.length; i++ ){
+ List cl = colors[ i ];
+ if ( cl == null ){
+ colorTbl[ i ] = EMPTY_COUNTER;
+ continue;
+ }
+ int nSlots = cl.size();
+ colorTbl[i] = (Counter[])cl.toArray( new Counter[ nSlots ] );
+
+ // the colors[ i ] - data is no longer needed: discard
+ colors[ i ] = null;
+ }
+
+ return colorTbl;
+ }
+
+ /**
+ * Converts the input image (must be TYPE_INT_RGB or
+ * TYPE_INT_ARGB) to an indexed image. Generating an adaptive
+ * palette with number of colors specified.
+ * @param bi the image to be processed.
+ * @param nColors number of colors in the palette
+ */
+ public static BufferedImage getIndexedImage( BufferedImage bi, int nColors) {
+ int w=bi.getWidth();
+ int h=bi.getHeight();
+
+ // Using 4 bits from RG & B.
+ List[] colors = createColorList( bi );
+
+ // now we have initialized the colors[] with lists of Counters.
+ // from now on, this data-structure is just read, not modified.
+ // convert it to Counter[][] for faster iteration
+ Counter[][] colorTbl = convertColorList( colors );
+
+ // this is no longer needed: discard
+ colors = null;
+
int nCubes=1;
int fCube=0;
Cube [] cubes = new Cube[nColors];
- cubes[0] = new Cube(colors, w*h);
-
+ cubes[0] = new Cube(colorTbl, w*h);
+
while (nCubes < nColors) {
while (cubes[fCube].isDone()) {
fCube++;
if (fCube == nCubes) break;
}
- if (fCube == nCubes) break;
+ if (fCube == nCubes) {
+ // System.out.println("fCube == nCubes" + fCube );
+ break;
+ }
Cube c = cubes[fCube];
Cube nc = c.split();
if (nc != null) {
+ // store the cube with less points towards the end of
+ // the array, so that fat cubes get more splits
if (nc.count > c.count) {
+ // new cube has more points: swap
Cube tmp = c; c= nc; nc = tmp;
}
int j = fCube;
int cnt = c.count;
for (int i=fCube+1; i<nCubes; i++) {
- if (cubes[i].count < cnt)
+ if (cubes[i].count < cnt)
break;
cubes[j++] = cubes[i];
}
@@ -400,7 +741,7 @@
cnt = nc.count;
while (j<nCubes) {
- if (cubes[j].count < cnt)
+ if (cubes[j].count < cnt)
break;
j++;
}
@@ -411,28 +752,16 @@
}
}
- byte [] r = new byte[nCubes];
- byte [] g = new byte[nCubes];
- byte [] b = new byte[nCubes];
- for (int i=0; i<nCubes; i++) {
- int val = cubes[i].averageColor();
- r[i] = (byte)((val>>16)&0xFF);
- g[i] = (byte)((val>> 8)&0xFF);
- b[i] = (byte)((val )&0xFF);
-
- // System.out.println("Color [" + i + "]: #" +
- // (((val>>16)<16)?"0":"") +
- // Integer.toHexString(val));
- }
- BufferedImage indexed;
-
+ // convert the remaining cubes to the colors they represent
+ byte[][] rgbTbl = computeRGB( nCubes, cubes );
// The JDK doesn't seem to dither the image correctly if I go
- // below 8bits per pixel. So I dither to an 8bit pallete
+ // below 8bits per pixel. So I dither to an 8bit palette
// image that only has nCubes colors. Then I copy the data to
// a lower bit depth image that I return.
- IndexColorModel icm=new IndexColorModel(8,nCubes,r,g,b);
- indexed =new BufferedImage
+ IndexColorModel icm= new IndexColorModel( 8, nCubes, rgbTbl[0], rgbTbl[1], rgbTbl[2] );
+
+ BufferedImage indexed =new BufferedImage
(w, h, BufferedImage.TYPE_BYTE_INDEXED, icm);
Graphics2D g2d=indexed.createGraphics();
g2d.setRenderingHint
@@ -446,24 +775,24 @@
for (bits=1; bits <=8; bits++) {
if ((1<<bits) >= nCubes) break;
}
- // System.out.println("Bits: " + bits + " Cubes: " + nCubes);
+// System.out.println("Bits: " + bits + " Cubes: " + nCubes);
- if (bits > 4)
+ if (bits > 4) {
// 8 bit image we are done...
return indexed;
+ }
// Create our low bit depth image...
if (bits ==3) bits = 4;
- ColorModel cm=new IndexColorModel(bits,nCubes,r,g,b);
- SampleModel sm = new MultiPixelPackedSampleModel
- (DataBuffer.TYPE_BYTE, w, h, bits);
- WritableRaster ras = Raster.createWritableRaster
- (sm, new Point(0,0));
+ ColorModel cm = new IndexColorModel(bits,nCubes,
+ rgbTbl[0], rgbTbl[1], rgbTbl[2] );
+ SampleModel sm;
+ sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, w, h, bits);
+ WritableRaster ras = Raster.createWritableRaster( sm, new Point(0,0));
// Copy the data to the low bitdepth image.
bi = indexed;
- indexed = new BufferedImage(cm, ras,
- bi.isAlphaPremultiplied(), null);
+ indexed = new BufferedImage(cm, ras, bi.isAlphaPremultiplied(), null);
GraphicsUtil.copyData(bi, indexed);
return indexed;
}
Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/gvt/event/AWTEventDispatcher.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/gvt/event/AWTEventDispatcher.java?rev=395847&r1=395846&r2=395847&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/gvt/event/AWTEventDispatcher.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/gvt/event/AWTEventDispatcher.java Fri Apr 21 04:00:05 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2001-2003 The Apache Software Foundation
+ Copyright 2001-2003 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -135,7 +135,7 @@
((baseTransform == null) || (!baseTransform.equals(t))))
// new Display transform so events are not where user
// thinks they were.
- eventQueue.clear();
+ eventQueue.clear();
baseTransform = t;
}
@@ -297,6 +297,10 @@
* @param listenerType the type of the listeners to return
*/
public EventListener [] getListeners(Class listenerType) {
+
+ // TODO the listeners should be cached per class in a map.
+ // this list is build again and again in mouse-event-handling...
+ // note: the cache must be flushed when the gListeners is modified
Object array =
Array.newInstance(listenerType,
glisteners.getListenerCount(listenerType));
@@ -327,6 +331,7 @@
public void setEventQueueMaxSize(int n) {
eventQueueMaxSize = n;
if (n == 0) eventQueue.clear();
+ // the current size is larger than the new size: shrink
while(eventQueue.size() > eventQueueMaxSize)
eventQueue.remove(0);
}
@@ -344,7 +349,7 @@
while (eventQueue.size() > eventQueueMaxSize)
// Limit how many events we queue - don't want
// user waiting forever for them to clear.
- eventQueue.remove(0);
+ eventQueue.remove(0);
}
return;
}
@@ -392,7 +397,7 @@
}
GraphicsNode node = root.nodeHitAt(gnp);
-
+
// If the receiving node has changed, send a notification
// check if we enter a new node
Point screenPos;
@@ -429,8 +434,7 @@
MouseEvent.
MOUSE_ENTERED,
evt.getWhen(),
- evt.
- getModifiers(),
+ evt.getModifiers(),
(float)gnp.getX(),
(float)gnp.getY(),
(int)Math.floor(p.getX()),
@@ -528,7 +532,8 @@
}
break;
default:
- throw new Error("Unknown Mouse Event type: "+evt.getID());
+ throw new IllegalArgumentException
+ ("Unknown Mouse Event type: "+evt.getID());
}
}
}
@@ -562,7 +567,8 @@
}
break;
default:
- throw new Error("Unknown Key Event type: "+evt.getID());
+ throw new IllegalArgumentException
+ ("Unknown Key Event type: "+evt.getID());
}
}
evt.consume();
@@ -571,12 +577,12 @@
private void incrementKeyTarget() {
// <!> FIXME TODO: Not implemented.
- throw new Error("Increment not implemented.");
+ throw new UnsupportedOperationException("Increment not implemented.");
}
private void decrementKeyTarget() {
// <!> FIXME TODO: Not implemented.
- throw new Error("Decrement not implemented.");
+ throw new UnsupportedOperationException("Decrement not implemented.");
}
/**
@@ -611,11 +617,32 @@
* @param e the input event
*/
protected boolean isNodeIncrementEvent(InputEvent e) {
- // TODO: Improve code readability!
- return ((e.getID() == nodeIncrementEventID) &&
- ((e instanceof KeyEvent) ?
- (((KeyEvent) e).getKeyCode() == nodeIncrementEventCode) : true) &&
- ((e.getModifiers() & nodeIncrementEventModifiers) != 0));
+ // DONE: Improve code readability!
+ // return ((e.getID() == nodeIncrementEventID) &&
+ // ((e instanceof KeyEvent) ?
+ // (((KeyEvent) e).getKeyCode() == nodeIncrementEventCode) : true) &&
+ // ((e.getModifiers() & nodeIncrementEventModifiers) != 0));
+
+ if ( e.getID() != nodeIncrementEventID ){
+ // not an incrementEvent: false
+ return false;
+ }
+
+ if (( e instanceof KeyEvent ) ){
+ if (( (KeyEvent) e).getKeyCode() != nodeIncrementEventCode ){
+ // it was a KeyEvent, but not a nodeIncrementEventCode : false
+ return false;
+ }
+ }
+ // here: it was not a KeyEvent at all OR a KeyEvent with
+ // nodeIncrementEventCode
+ if (( e.getModifiers() & nodeIncrementEventModifiers ) == 0 ) {
+ // no nodeIncrementEventModifiers were set: false
+ return false;
+ }
+
+ // this is the only path to success...
+ return true;
}
/**
@@ -623,11 +650,31 @@
* false otherwise.
*/
protected boolean isNodeDecrementEvent(InputEvent e) {
- // TODO: Improve code readability!
- return ((e.getID() == nodeDecrementEventID) &&
- ((e instanceof KeyEvent) ?
- ( ((KeyEvent) e).getKeyCode() == nodeDecrementEventCode) : true) &&
- ((e.getModifiers() & nodeDecrementEventModifiers) != 0 ));
+ // DONE: Improve code readability! YES !!
+ // return ((e.getID() == nodeDecrementEventID) &&
+ // ((e instanceof KeyEvent) ?
+ // ( ((KeyEvent) e).getKeyCode() == nodeDecrementEventCode) : true) &&
+ // ((e.getModifiers() & nodeDecrementEventModifiers) != 0 ));
+
+ if ( e.getID() != nodeDecrementEventID ){
+ // not an nodeDecrementEvent: false
+ return false;
+ }
+
+ if (( e instanceof KeyEvent ) ){
+ if (( (KeyEvent) e).getKeyCode() != nodeDecrementEventCode ){
+ // it was a KeyEvent, but not a nodeDecrementEventCode : false
+ return false;
+ }
+ }
+ // here: it was not a KeyEvent at all OR a KeyEvent with
+ // nodeIncrementEventCode
+ if (( e.getModifiers() & nodeDecrementEventModifiers ) == 0 ) {
+ // no nodeDecrementEventModifiers were set: false
+ return false;
+ }
+ // this is the only path to success...
+ return true;
}
}
Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/gvt/TextSelectionManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/gvt/TextSelectionManager.java?rev=395847&r1=395846&r2=395847&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/gvt/TextSelectionManager.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/gvt/TextSelectionManager.java Fri Apr 21 04:00:05 2006
@@ -1,18 +1,18 @@
/*
- Copyright 1999-2003 The Apache Software Foundation
+Copyright 1999-2003 The Apache Software Foundation
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
@@ -142,14 +142,14 @@
* @param color the new color of the selection overlay
*/
public void setSelectionOverlayColor(Color color) {
- this.selectionOverlayColor = color;
+ this.selectionOverlayColor = color;
}
/**
* Returns the color of the selection overlay.
*/
public Color getSelectionOverlayColor() {
- return selectionOverlayColor;
+ return selectionOverlayColor;
}
/**
@@ -159,14 +159,14 @@
* @param color the new color of the outline of the selection overlay
*/
public void setSelectionOverlayStrokeColor(Color color) {
- this.selectionOverlayStrokeColor = color;
+ this.selectionOverlayStrokeColor = color;
}
/**
* Returns the color of the outline of the selection overlay.
*/
public Color getSelectionOverlayStrokeColor() {
- return selectionOverlayStrokeColor;
+ return selectionOverlayStrokeColor;
}
/**
@@ -176,7 +176,7 @@
* @param state true implies the selection overlay will be in XOR mode
*/
public void setSelectionOverlayXORMode(boolean state) {
- this.xorMode = state;
+ this.xorMode = state;
}
/**
@@ -184,7 +184,7 @@
* otherwise.
*/
public boolean isSelectionOverlayXORMode() {
- return xorMode;
+ return xorMode;
}
/**
@@ -212,7 +212,7 @@
* Clears the selection.
*/
public void clearSelection() {
- textSelector.clearSelection();
+ textSelector.clearSelection();
}
/**
@@ -338,19 +338,19 @@
Shape s = at.createTransformedShape(selectionHighlight);
Graphics2D g2d = (Graphics2D)g;
- if (xorMode) {
- g2d.setColor(Color.black);
- g2d.setXORMode(Color.white);
- g2d.fill(s);
- } else {
- g2d.setColor(selectionOverlayColor);
- g2d.fill(s);
- if (selectionOverlayStrokeColor != null) {
- g2d.setStroke(new java.awt.BasicStroke(1.0f));
- g2d.setColor(selectionOverlayStrokeColor);
- g2d.draw(s);
- }
- }
+ if (xorMode) {
+ g2d.setColor(Color.black);
+ g2d.setXORMode(Color.white);
+ g2d.fill(s);
+ } else {
+ g2d.setColor(selectionOverlayColor);
+ g2d.fill(s);
+ if (selectionOverlayStrokeColor != null) {
+ g2d.setStroke(new java.awt.BasicStroke(1.0f));
+ g2d.setColor(selectionOverlayStrokeColor);
+ g2d.draw(s);
+ }
+ }
}
}
}
Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/svg/JSVGComponent.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/svg/JSVGComponent.java?rev=395847&r1=395846&r2=395847&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/svg/JSVGComponent.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/swing/svg/JSVGComponent.java Fri Apr 21 04:00:05 2006
@@ -358,6 +358,17 @@
protected boolean isInteractiveDocument;
/**
+ * Set to true before component calls setDisableInteractors
+ * so it knows that the users isn't the one calling it.
+ */
+ protected boolean selfCallingDisableInteractions = false;
+
+ /**
+ * Set to true if the user ever calls setDisableInteractions
+ */
+ protected boolean userSetDisableInteractions = false;
+
+ /**
* The document state.
*/
protected int documentState;
@@ -405,6 +416,42 @@
setSVGDocument(null);
}
+ public void setDisableInteractions(boolean b) {
+ super.setDisableInteractions(b);
+ if (!selfCallingDisableInteractions)
+ userSetDisableInteractions = true;
+ }
+
+ /**
+ * Clears the boolean that indicates the 'user'
+ * has set disable interactions so that the canvas
+ * uses the value from documents.
+ */
+ public void clearUserSetDisableInteractions() {
+ userSetDisableInteractions = false;
+ updateZoomAndPanEnable(svgDocument);
+ }
+
+ /**
+ * Enables/Disables Zoom And Pan based on the zoom and
+ * pan attribute of the currently installed document,
+ * Unless the user has set the Interactions State.
+ */
+ public void updateZoomAndPanEnable(Document doc) {
+ if (userSetDisableInteractions) return;
+ if (doc == null) return;
+ try {
+ Element root = doc.getDocumentElement();
+ String znp = root.getAttributeNS
+ (null, SVGConstants.SVG_ZOOM_AND_PAN_ATTRIBUTE);
+ boolean enable = SVGConstants.SVG_MAGNIFY_VALUE.equals(znp);
+ selfCallingDisableInteractions = true;
+ setDisableInteractions(!enable);
+ } finally {
+ selfCallingDisableInteractions = false;
+ }
+ }
+
/**
* Indicates if the canvas should recenter the content after
* the canvas is resized. If true it will try and keep the
@@ -706,11 +753,7 @@
bridgeContext.setDynamicState(BridgeContext.INTERACTIVE);
}
- Element root = doc.getDocumentElement();
- String znp = root.getAttributeNS
- (null, SVGConstants.SVG_ZOOM_AND_PAN_ATTRIBUTE);
-
- setDisableInteractions(!znp.equals(SVGConstants.SVG_MAGNIFY_VALUE));
+ updateZoomAndPanEnable(doc);
nextGVTTreeBuilder = new GVTTreeBuilder(doc, bridgeContext);
nextGVTTreeBuilder.setPriority(Thread.MIN_PRIORITY);
Modified: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/print/PrintTranscoder.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/print/PrintTranscoder.java?rev=395847&r1=395846&r2=395847&view=diff
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/print/PrintTranscoder.java (original)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/print/PrintTranscoder.java Fri Apr 21 04:00:05 2006
@@ -244,6 +244,10 @@
pageFormat = tmpPageFormat;
}
+ // Set printable before showing printer dialog so
+ // it can update the pageFormat if it wishes...
+ printerJob.setPrintable(this, pageFormat);
+
//
// If required, pop up a dialog to select the printer
//
@@ -258,7 +262,6 @@
}
// Print now
- printerJob.setPrintable(this, pageFormat);
printerJob.print();
}