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/22 18:05:18 UTC
svn commit: r396138 [2/3] - in
/xmlgraphics/batik/trunk/sources/org/apache/batik: apps/rasterizer/
apps/svgbrowser/ bridge/ css/dom/ css/engine/ css/engine/value/ dom/svg/
ext/awt/image/rendered/ extension/ gvt/event/ swing/gvt/ swing/svg/
transcoder/p...
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/CSSEngine.java Sat Apr 22 09:05:15 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2002-2006 The Apache Software Foundation
+ Copyright 2002-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.
@@ -39,6 +39,7 @@
import org.apache.batik.css.parser.ExtendedParser;
import org.apache.batik.util.CSSConstants;
import org.apache.batik.util.ParsedURL;
+
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.DocumentHandler;
import org.w3c.css.sac.InputSource;
@@ -56,6 +57,7 @@
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.events.MutationEvent;
+
/**
* This is the base class for all the CSS engines.
*
@@ -127,7 +129,7 @@
* The CSS context.
*/
protected CSSContext cssContext;
-
+
/**
* The associated document.
*/
@@ -223,7 +225,7 @@
* The style attribute local name.
*/
protected String styleLocalName;
-
+
/**
* The class attribute namespace URI.
*/
@@ -233,7 +235,7 @@
* The class attribute local name.
*/
protected String classLocalName;
-
+
/**
* The non CSS presentational hints.
*/
@@ -754,11 +756,19 @@
Node attr = attrs.item(i);
String an = attr.getNodeName();
if (nonCSSPresentationalHints.contains(an)) {
+ String attrValue = attr.getNodeValue(); // -- dvh
try {
LexicalUnit lu;
lu = parser.parsePropertyValue(attr.getNodeValue());
ph.property(an, lu, false);
} catch (Exception e) {
+
+ System.err.println("\n***** CSSEngine: exception property.syntax.error:" + e ); // ---
+ System.err.println("\nAttrValue:" + attrValue );
+ System.err.println("\nException:" + e.getClass().getName() );
+ e.printStackTrace( System.err ); // ---
+ System.err.println("\n***** CSSEngine: exception...." ); // ---
+
String m = e.getMessage();
if (m == null) m = "";
String u = ((documentURI == null)?"<unknown>":
@@ -808,6 +818,11 @@
parser.parseStyleDeclaration(style);
styleDeclarationDocumentHandler.styleMap = null;
} catch (Exception e) {
+ System.err.println("\n***** CSSEngine: exception style.syntax.error:" + e ); // ---
+ System.err.println("\nException:" + e.getClass().getName() );
+ e.printStackTrace( System.err ); // ---
+ System.err.println("\n***** CSSEngine: exception...." ); // ---
+
String m = e.getMessage();
if (m == null) m = "";
String u = ((documentURI == null)?"<unknown>":
@@ -861,14 +876,14 @@
}
Value value = sm.getValue(propidx);
- if (sm.isComputed(propidx))
+ if (sm.isComputed(propidx))
return value;
Value result = value;
ValueManager vm = valueManagers[propidx];
CSSStylableElement p = getParentCSSStylableElement(elt);
if (value == null) {
- if ((p == null) || !vm.isInheritedProperty())
+ if ((p == null) || !vm.isInheritedProperty())
result = vm.getDefaultValue();
} else if ((p != null) && (value == InheritValue.INSTANCE)) {
result = null;
@@ -974,7 +989,7 @@
* Called with a non-shorthand property name and it's value.
*/
public void setMainProperty(String name, Value v, boolean important);
- };
+ }
public void setMainProperties
(CSSStylableElement elt, final MainPropertyReceiver dst,
@@ -1004,7 +1019,7 @@
ph.property(pname, lu, important);
} catch (Exception e) {
String m = e.getMessage();
- if (m == null) m = "";
+ if (m == null) m = ""; // todo - better handling of NPE
String u = ((documentURI == null)?"<unknown>":
documentURI.toString());
String s = Messages.formatMessage
@@ -1151,7 +1166,7 @@
return;
}
- try {
+ try {
// Check that access to the uri is allowed
ParsedURL pDocURL = null;
if (documentURI != null) {
@@ -1159,10 +1174,10 @@
}
ParsedURL pURL = new ParsedURL(uri);
cssContext.checkLoadExternalResource(pURL, pDocURL);
-
+
parseStyleSheet(ss, new InputSource(uri.toString()), uri);
- } catch (SecurityException e) {
- throw e;
+ } catch (SecurityException e) {
+ throw e;
} catch (Exception e) {
String m = e.getMessage();
if (m == null) m = "";
@@ -1408,23 +1423,23 @@
* CSSEngine object.
*/
protected boolean mediaMatch(SACMediaList ml) {
- if (media == null ||
+ if (media == null ||
ml == null ||
media.getLength() == 0 ||
ml.getLength() == 0) {
- return true;
- }
- for (int i = 0; i < ml.getLength(); i++) {
+ return true;
+ }
+ for (int i = 0; i < ml.getLength(); i++) {
if (ml.item(i).equalsIgnoreCase("all"))
return true;
- for (int j = 0; j < media.getLength(); j++) {
- if (media.item(j).equalsIgnoreCase("all") ||
+ for (int j = 0; j < media.getLength(); j++) {
+ if (media.item(j).equalsIgnoreCase("all") ||
ml.item(i).equalsIgnoreCase(media.item(j))) {
- return true;
- }
- }
- }
- return false;
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
@@ -1434,7 +1449,7 @@
extends DocumentAdapter
implements ShorthandManager.PropertyHandler {
public StyleMap styleMap;
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#property(String,LexicalUnit,boolean)}.
@@ -1467,7 +1482,7 @@
extends DocumentAdapter
implements ShorthandManager.PropertyHandler {
public StyleDeclaration styleDeclaration;
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#property(String,LexicalUnit,boolean)}.
@@ -1509,27 +1524,27 @@
public void startDocument(InputSource source)
throws CSSException {
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#endDocument(InputSource)}.
*/
public void endDocument(InputSource source) throws CSSException {
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#ignorableAtRule(String)}.
*/
public void ignorableAtRule(String atRule) throws CSSException {
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#importStyle(String,SACMediaList,String)}.
*/
public void importStyle(String uri,
- SACMediaList media,
+ SACMediaList media,
String defaultNamespaceURI)
throws CSSException {
ImportRule ir = new ImportRule();
@@ -1545,7 +1560,7 @@
}
styleSheet.append(ir);
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#startMedia(SACMediaList)}.
@@ -1557,7 +1572,7 @@
styleSheet.append(mr);
styleSheet = mr;
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#endMedia(SACMediaList)}.
@@ -1565,15 +1580,15 @@
public void endMedia(SACMediaList media) throws CSSException {
styleSheet = styleSheet.getParent();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#startPage(String,String)}.
- */
+ */
public void startPage(String name, String pseudo_page)
throws CSSException {
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#endPage(String,String)}.
@@ -1581,7 +1596,7 @@
public void endPage(String name, String pseudo_page)
throws CSSException {
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#startFontFace()}.
@@ -1589,7 +1604,7 @@
public void startFontFace() throws CSSException {
styleDeclaration = new StyleDeclaration();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#endFontFace()}.
@@ -1602,7 +1617,7 @@
sm.putValue(idx, styleDeclaration.getValue(i));
sm.putImportant(idx, styleDeclaration.getPriority(i));
// Not sure on this..
- sm.putOrigin(idx, StyleMap.AUTHOR_ORIGIN);
+ sm.putOrigin(idx, StyleMap.AUTHOR_ORIGIN);
}
styleDeclaration = null;
@@ -1615,7 +1630,7 @@
if (base != null) purl = new ParsedURL(base);
fontFaces.add(new FontFaceRule(sm, purl));
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#startSelector(SelectorList)}.
@@ -1627,7 +1642,7 @@
styleRule.setStyleDeclaration(styleDeclaration);
styleSheet.append(styleRule);
}
-
+
/**
* <b>SAC</b>: Implements {@link
* org.w3c.css.sac.DocumentHandler#endSelector(SelectorList)}.
@@ -1662,7 +1677,9 @@
}
/**
- * Provides an adapter for the DocumentHandler interface.
+ * Provides an (empty) adapter for the DocumentHandler interface.
+ * Most methods just throw an UnsupportedOperationException, so
+ * the subclasses <i>must</i> override them with 'real' methods.
*/
protected static class DocumentAdapter implements DocumentHandler {
@@ -1670,131 +1687,130 @@
* <b>SAC</b>: Implements {@link
* DocumentHandler#startDocument(InputSource)}.
*/
- public void startDocument(InputSource source)
- throws CSSException {
- throw new InternalError();
+ public void startDocument(InputSource source){
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#endDocument(InputSource)}.
*/
- public void endDocument(InputSource source) throws CSSException {
- throw new InternalError();
+ public void endDocument(InputSource source) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#comment(String)}.
*/
- public void comment(String text) throws CSSException {
+ public void comment(String text) {
// We always ignore the comments.
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#ignorableAtRule(String)}.
*/
- public void ignorableAtRule(String atRule) throws CSSException {
- throw new InternalError();
+ public void ignorableAtRule(String atRule) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#namespaceDeclaration(String,String)}.
*/
- public void namespaceDeclaration(String prefix, String uri)
- throws CSSException {
- throw new InternalError();
+ public void namespaceDeclaration(String prefix, String uri) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#importStyle(String,SACMediaList,String)}.
*/
public void importStyle(String uri,
- SACMediaList media,
- String defaultNamespaceURI)
- throws CSSException {
- throw new InternalError();
+ SACMediaList media,
+ String defaultNamespaceURI) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#startMedia(SACMediaList)}.
*/
- public void startMedia(SACMediaList media) throws CSSException {
- throw new InternalError();
+ public void startMedia(SACMediaList media) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#endMedia(SACMediaList)}.
*/
- public void endMedia(SACMediaList media) throws CSSException {
- throw new InternalError();
+ public void endMedia(SACMediaList media) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#startPage(String,String)}.
- */
- public void startPage(String name, String pseudo_page)
- throws CSSException {
- throw new InternalError();
+ */
+ public void startPage(String name, String pseudo_page) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#endPage(String,String)}.
*/
- public void endPage(String name, String pseudo_page)
- throws CSSException {
- throw new InternalError();
+ public void endPage(String name, String pseudo_page) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link DocumentHandler#startFontFace()}.
*/
- public void startFontFace() throws CSSException {
- throw new InternalError();
+ public void startFontFace() {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link DocumentHandler#endFontFace()}.
*/
- public void endFontFace() throws CSSException {
- throw new InternalError();
+ public void endFontFace() {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#startSelector(SelectorList)}.
*/
- public void startSelector(SelectorList selectors) throws CSSException {
- throw new InternalError();
+ public void startSelector(SelectorList selectors) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#endSelector(SelectorList)}.
*/
- public void endSelector(SelectorList selectors) throws CSSException {
- throw new InternalError();
+ public void endSelector(SelectorList selectors) {
+ throwUnsupportedEx();
}
-
+
/**
* <b>SAC</b>: Implements {@link
* DocumentHandler#property(String,LexicalUnit,boolean)}.
*/
- public void property(String name, LexicalUnit value, boolean important)
- throws CSSException {
- throw new InternalError();
+ public void property(String name, LexicalUnit value, boolean important) {
+ throwUnsupportedEx();
+ }
+
+
+ private void throwUnsupportedEx(){
+ throw new UnsupportedOperationException("you try to use an empty method in Adapter-class" );
}
}
// CSS events /////////////////////////////////////////////////////////
-
+
protected final static CSSEngineListener[] LISTENER_ARRAY =
new CSSEngineListener[0];
@@ -1829,7 +1845,7 @@
}
// Dynamic updates ////////////////////////////////////////////////////
-
+
/**
* Called when the inline style of the given element has been updated.
*/
@@ -1844,7 +1860,7 @@
}
switch (attrChange) {
- case MutationEvent.ADDITION:
+ case MutationEvent.ADDITION: // intentional fall-through
case MutationEvent.MODIFICATION:
if (newValue.length() > 0) {
element = elt;
@@ -1904,11 +1920,11 @@
boolean cl = (colorIndex == -1)
? false
: updated[colorIndex];
-
+
for (int i = getNumberOfProperties() - 1; i >= 0; --i) {
if (updated[i]) {
count++;
- }
+ }
else if ((fs && style.isFontSizeRelative(i)) ||
(lh && style.isLineHeightRelative(i)) ||
(cl && style.isColorRelative(i))) {
@@ -1933,7 +1949,7 @@
default:
// Must not happen
- throw new InternalError("Invalid attrChangeType");
+ throw new IllegalStateException("Invalid attrChangeType");
}
}
@@ -1954,10 +1970,10 @@
/**
* Invalidates all the properties of the given node.
- *
+ *
*/
- protected void invalidateProperties(Node node,
- int [] properties,
+ protected void invalidateProperties(Node node,
+ int [] properties,
boolean [] updated,
boolean recascade) {
@@ -1968,12 +1984,10 @@
StyleMap style = elt.getComputedStyleMap(null);
if (style == null)
return; // Nothing to invalidate.
-
+
boolean [] diffs = new boolean[getNumberOfProperties()];
if (updated != null) {
- for (int i=0; i< updated.length; i++) {
- diffs[i] = updated[i];
- }
+ System.arraycopy( updated, 0, diffs, 0, updated.length );
}
if (properties != null) {
for (int i=0; i<properties.length; i++) {
@@ -2038,7 +2052,7 @@
* again to see if the any new rules apply (or old rules don't
* apply).
*/
- protected void propagateChanges(Node node, int[] props,
+ protected void propagateChanges(Node node, int[] props,
boolean recascade) {
if (!(node instanceof CSSStylableElement))
return;
@@ -2098,7 +2112,7 @@
int [] inherited = props;
if (props != null) {
- // Filter out uninheritable properties when we
+ // Filter out uninheritable properties when we
// propogate to children.
int count = 0;
for (int i=0; i<props.length; i++) {
@@ -2106,7 +2120,7 @@
if (vm.isInheritedProperty()) count++;
else props[i] = -1;
}
-
+
if (count == 0) {
// nothing to propogate for sure
inherited = null;
@@ -2123,10 +2137,7 @@
n != null;
n = getCSSNextSibling(n)) {
if (n.getNodeType() == Node.ELEMENT_NODE) {
- // XXX Should this invalidateProperties be called on eng?
- // In r216064 with CSSImportedElementRoot, the imported
- // element's CSSEngine was indeed used.
- // CSSEngine eng = cssContext.getCSSEngineForElement((Element) n);
+ CSSEngine eng = cssContext.getCSSEngineForElement((Element) n);
invalidateProperties(n, inherited, null, recascade);
}
}
@@ -2196,9 +2207,9 @@
// The current value has a greater priority
return;
}
-
+
switch (attrChange) {
- case MutationEvent.ADDITION:
+ case MutationEvent.ADDITION: // intentional fall-through
case MutationEvent.MODIFICATION:
element = elt;
try {
@@ -2226,7 +2237,7 @@
}
break;
- case MutationEvent.REMOVAL:
+ case MutationEvent.REMOVAL:
{
int [] invalid = { idx };
invalidateProperties(elt, invalid, null, true);
@@ -2288,10 +2299,10 @@
}
String attrNS = attr.getNamespaceURI();
- String name = ((attrNS == null) ?
+ String name = ((attrNS == null) ?
attr.getNodeName() :
attr.getLocalName());
-
+
CSSStylableElement elt = (CSSStylableElement)e;
StyleMap style = elt.getComputedStyleMap(null);
if (style != null) {
@@ -2358,7 +2369,7 @@
if (newNode instanceof CSSStyleSheetNode) {
styleSheetNodes = null;
// Invalidate all the CSSStylableElements in the document.
- invalidateProperties(document.getDocumentElement(),
+ invalidateProperties(document.getDocumentElement(),
null, null, true);
} else if (newNode instanceof CSSStylableElement) {
// Invalidate the CSSStylableElement siblings, to
@@ -2399,7 +2410,7 @@
styleSheetNodes = null;
// Invalidate all the CSSStylableElements in the document.
- invalidateProperties(document.getDocumentElement(),
+ invalidateProperties(document.getDocumentElement(),
null, null, true);
} else if (removedStylableElementSibling != null) {
// Invalidate the CSSStylableElement siblings, to
@@ -2421,7 +2432,7 @@
if (getCSSParentNode(text) instanceof CSSStyleSheetNode) {
styleSheetNodes = null;
// Invalidate all the CSSStylableElements in the document.
- invalidateProperties(document.getDocumentElement(),
+ invalidateProperties(document.getDocumentElement(),
null, null, true);
}
}
@@ -2535,7 +2546,7 @@
if (et instanceof CSSStyleSheetNode) {
styleSheetNodes = null;
// Invalidate all the CSSStylableElements in the document.
- invalidateProperties(document.getDocumentElement(),
+ invalidateProperties(document.getDocumentElement(),
null, null, true);
return;
}
@@ -2584,7 +2595,7 @@
styleSheetNodes = null;
// Invalidate all the CSSStylableElements in the document.
- invalidateProperties(document.getDocumentElement(),
+ invalidateProperties(document.getDocumentElement(),
null, null, true);
} else if (removedStylableElementSibling != null) {
// Invalidate the CSSStylableElement siblings, to
@@ -2609,7 +2620,7 @@
if (n.getParentNode() instanceof CSSStyleSheetNode) {
styleSheetNodes = null;
// Invalidate all the CSSStylableElements in the document.
- invalidateProperties(document.getDocumentElement(),
+ invalidateProperties(document.getDocumentElement(),
null, null, true);
}
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/value/AbstractColorManager.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/value/AbstractColorManager.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/value/AbstractColorManager.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/css/engine/value/AbstractColorManager.java Sat Apr 22 09:05:15 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2002-2003 The Apache Software Foundation
+ Copyright 2002-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.
@@ -33,7 +33,7 @@
* @version $Id$
*/
public abstract class AbstractColorManager extends IdentifierManager {
-
+
/**
* The identifier values.
*/
@@ -205,7 +205,7 @@
}
// Must be a system color...
if (values.get(ident) == null) {
- throw new InternalError();
+ throw new IllegalStateException("Not a system-color:" + ident );
}
return engine.getCSSContext().getSystemColor(ident);
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGDOMImplementation.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGDOMImplementation.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGDOMImplementation.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGDOMImplementation.java Sat Apr 22 09:05:15 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2000-2003 The Apache Software Foundation
+ Copyright 2000-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.
@@ -26,24 +26,18 @@
import org.apache.batik.css.engine.value.ShorthandManager;
import org.apache.batik.css.engine.value.ValueManager;
import org.apache.batik.css.parser.ExtendedParser;
-import org.apache.batik.css.parser.ExtendedParserWrapper;
import org.apache.batik.dom.AbstractDocument;
import org.apache.batik.dom.AbstractStylableDocument;
import org.apache.batik.dom.ExtensibleDOMImplementation;
import org.apache.batik.dom.GenericDocumentType;
-import org.apache.batik.dom.GenericElement;
-import org.apache.batik.dom.GenericElementNS;
-import org.apache.batik.dom.StyleSheetFactory;
import org.apache.batik.dom.events.DocumentEventSupport;
import org.apache.batik.dom.util.CSSStyleDeclarationFactory;
import org.apache.batik.dom.util.DOMUtilities;
import org.apache.batik.dom.util.HashTable;
import org.apache.batik.i18n.LocalizableSupport;
import org.apache.batik.util.SVGConstants;
-import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.css.sac.InputSource;
-import org.w3c.css.sac.Parser;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
@@ -52,7 +46,6 @@
import org.w3c.dom.Node;
import org.w3c.dom.css.CSSStyleDeclaration;
import org.w3c.dom.css.CSSStyleSheet;
-import org.w3c.dom.css.DOMImplementationCSS;
import org.w3c.dom.css.ViewCSS;
import org.w3c.dom.events.Event;
import org.w3c.dom.stylesheets.StyleSheet;
@@ -65,9 +58,9 @@
* @version $Id$
*/
public class SVGDOMImplementation
- extends ExtensibleDOMImplementation
+ extends ExtensibleDOMImplementation
implements CSSStyleDeclarationFactory {
-
+
/**
* The SVG namespace uri.
*/
@@ -105,12 +98,12 @@
(RESOURCES, getClass().getClassLoader());
}
- public CSSEngine createCSSEngine(AbstractStylableDocument doc,
+ public CSSEngine createCSSEngine(AbstractStylableDocument doc,
CSSContext ctx,
ExtendedParser ep,
- ValueManager [] vms,
+ ValueManager [] vms,
ShorthandManager [] sms) {
-
+
URL durl = ((SVGOMDocument)doc).getURLObject();
CSSEngine result = new SVGCSSEngine(doc, durl, ep, vms, sms, ctx);
@@ -164,7 +157,8 @@
* DOMImplementationCSS#createCSSStyleSheet(String,String)}.
*/
public CSSStyleSheet createCSSStyleSheet(String title, String media) {
- throw new InternalError("Not implemented");
+
+ throw new UnsupportedOperationException("Not implemented");
}
// CSSStyleDeclarationFactory ///////////////////////////////////////////
@@ -174,7 +168,7 @@
* @return a CSSOMStyleDeclaration instance.
*/
public CSSStyleDeclaration createCSSStyleDeclaration() {
- throw new InternalError("Not implemented");
+ throw new UnsupportedOperationException("Not implemented");
}
// StyleSheetFactory /////////////////////////////////////////////
@@ -184,14 +178,14 @@
* processing instruction or return null.
*/
public StyleSheet createStyleSheet(Node n, HashTable attrs) {
- throw new InternalError("Not implemented");
+ throw new UnsupportedOperationException("Not implemented");
}
/**
* Returns the user-agent stylesheet.
*/
public CSSStyleSheet getUserAgentStyleSheet() {
- throw new InternalError("Not implemented");
+ throw new UnsupportedOperationException("Not implemented");
}
/**
@@ -494,7 +488,7 @@
return new SVGOMAElement(prefix, (AbstractDocument)doc);
}
}
-
+
/**
* To create a 'altGlyph' element.
*/
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGOMStyleElement.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGOMStyleElement.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGOMStyleElement.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGOMStyleElement.java Sat Apr 22 09:05:15 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2000-2003 The Apache Software Foundation
+ Copyright 2000-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.
@@ -115,15 +115,15 @@
text = sb.toString();
}
URL burl = null;
+ String bu= "";
try {
- String bu = getBaseURI();
+ bu = getBaseURI();
if (bu != null) {
burl = new URL(bu);
}
} catch (MalformedURLException ex) {
- // !!! TODO
- ex.printStackTrace();
- throw new InternalError();
+ String msg = "MalformedURLException:" + ex.getMessage() + ':' + bu;
+ throw new IllegalArgumentException( msg );
}
String media = getAttributeNS(null, SVG_MEDIA_ATTRIBUTE);
styleSheet = e.parseStyleSheet(text, burl, media);
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGStylableElement.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGStylableElement.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGStylableElement.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/dom/svg/SVGStylableElement.java Sat Apr 22 09:05:15 2006
@@ -1,6 +1,6 @@
/*
- Copyright 2001-2006 The Apache Software Foundation
+ Copyright 2001-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.
@@ -76,7 +76,7 @@
protected SVGStylableElement(String prefix, AbstractDocument owner) {
super(prefix, owner);
}
-
+
/**
* Returns the override style declaration for this element.
*/
@@ -89,7 +89,7 @@
}
// CSSStylableElement //////////////////////////////////////////
-
+
/**
* Returns the computed style of this element/pseudo-element.
*/
@@ -120,21 +120,22 @@
/**
* Returns the CSS base URL of this element.
+ * @throws IllegalArgumentException when the result of getBaseURI()
+ * cannot be used as an URL.
*/
public URL getCSSBase() {
+ if (getXblBoundElement() != null) {
+ return null;
+ }
+ String bu = getBaseURI();
+ if (bu == null) {
+ return null;
+ }
try {
- if (getXblBoundElement() != null) {
- return null;
- }
- String bu = getBaseURI();
- if (bu == null) {
- return null;
- }
return new URL(bu);
} catch (MalformedURLException e) {
- // !!! TODO
- e.printStackTrace();
- throw new InternalError();
+ String msg = "MalformedURLException:" + e.getMessage() + ':' + bu;
+ throw new IllegalArgumentException( msg );
}
}
@@ -189,7 +190,7 @@
CSSEngine eng = ((SVGOMDocument)getOwnerDocument()).getCSSEngine();
int idx = eng.getPropertyIndex(name);
- if (idx == -1)
+ if (idx == -1)
return null;
if (idx > SVGCSSEngine.FINAL_INDEX) {
@@ -205,13 +206,13 @@
case SVGCSSEngine.STROKE_INDEX:
result = new PresentationAttributePaintValue(eng, name);
break;
-
+
case SVGCSSEngine.FLOOD_COLOR_INDEX:
case SVGCSSEngine.LIGHTING_COLOR_INDEX:
case SVGCSSEngine.STOP_COLOR_INDEX:
result = new PresentationAttributeColorValue(eng, name);
break;
-
+
default:
result = new PresentationAttributeValue(eng, name);
}
@@ -539,7 +540,7 @@
extends CSSOMStoredStyleDeclaration
implements LiveAttributeValue,
CSSEngine.MainPropertyReceiver {
-
+
/**
* Whether the mutation comes from this object.
*/
@@ -640,7 +641,7 @@
*/
public void setMainProperty(String name, Value v, boolean important) {
int idx = cssEngine.getPropertyIndex(name);
- if (idx == -1)
+ if (idx == -1)
return; // unknown property
int i;
@@ -648,7 +649,7 @@
if (idx == declaration.getIndex(i))
break;
}
- if (i < declaration.size())
+ if (i < declaration.size())
declaration.put(i, v, idx, important);
else
declaration.append(v, idx, important);
@@ -665,7 +666,7 @@
/**
* Creates a new OverrideStyleDeclaration.
*/
- public OverrideStyleDeclaration(CSSEngine eng) {
+ protected OverrideStyleDeclaration(CSSEngine eng) {
super(eng);
declaration = new org.apache.batik.css.engine.StyleDeclaration();
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java Sat Apr 22 09:05:15 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/trunk/sources/org/apache/batik/extension/StylableExtensionElement.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/extension/StylableExtensionElement.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/extension/StylableExtensionElement.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/extension/StylableExtensionElement.java Sat Apr 22 09:05:15 2006
@@ -1,6 +1,6 @@
/*
- Copyright 1999-2003,2006 The Apache Software Foundation
+ Copyright 1999-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.
@@ -25,6 +25,7 @@
import org.apache.batik.css.engine.StyleDeclarationProvider;
import org.apache.batik.css.engine.StyleMap;
import org.apache.batik.dom.AbstractDocument;
+
import org.w3c.dom.Node;
import org.w3c.dom.css.CSSStyleDeclaration;
import org.w3c.dom.css.CSSValue;
@@ -71,7 +72,7 @@
}
// CSSStylableElement //////////////////////////////////////////
-
+
/**
* Returns the computed style of this element/pseudo-element.
*/
@@ -102,19 +103,23 @@
/**
* Returns the CSS base URL of this element.
+ * @throws IllegalArgumentException when {@link #getBaseURI } returns an invalid URL.
+ * The information from the MalformedURLException
+ * is passed to the IllegalArgumentException
+ *
*/
public URL getCSSBase() {
+ String bu = "";
if (cssBase == null) {
try {
- String bu = getBaseURI();
+ bu = getBaseURI();
if (bu == null) {
return null;
}
cssBase = new URL(bu);
} catch (MalformedURLException e) {
- // !!! TODO
- e.printStackTrace();
- throw new InternalError();
+ String msg = "MalformedURLException:" + e.getMessage() + ':' + bu;
+ throw new IllegalArgumentException( msg );
}
}
return cssBase;
@@ -150,7 +155,7 @@
* <b>DOM</b>: Implements {@link org.w3c.dom.svg.SVGStylable#getStyle()}.
*/
public CSSStyleDeclaration getStyle() {
- throw new InternalError("Not implemented");
+ throw new UnsupportedOperationException("Not implemented");
}
/**
@@ -158,7 +163,7 @@
* org.w3c.dom.svg.SVGStylable#getPresentationAttribute(String)}.
*/
public CSSValue getPresentationAttribute(String name) {
- throw new InternalError("Not implemented");
+ throw new UnsupportedOperationException("Not implemented");
}
/**
@@ -166,6 +171,6 @@
* org.w3c.dom.svg.SVGStylable#getClassName()}.
*/
public SVGAnimatedString getClassName() {
- throw new InternalError("Not implemented");
+ throw new UnsupportedOperationException("Not implemented");
}
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/event/AbstractAWTEventDispatcher.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/event/AbstractAWTEventDispatcher.java?rev=396138&r1=396137&r2=396138&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/event/AbstractAWTEventDispatcher.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/gvt/event/AbstractAWTEventDispatcher.java Sat Apr 22 09:05:15 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.
@@ -139,7 +139,7 @@
((baseTransform == null) || (!baseTransform.equals(t))))
// new Display transform so events are not where user
// thinks they were.
- eventQueue.clear();
+ eventQueue.clear();
baseTransform = t;
}
@@ -326,6 +326,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));
@@ -356,6 +360,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);
}
@@ -373,7 +378,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;
}
@@ -401,28 +406,28 @@
if (t.getLockingKeyState(KeyEvent.VK_KANA_LOCK)) {
lockState++;
}
- } catch (java.lang.UnsupportedOperationException ex) {
+ } catch (UnsupportedOperationException ex) {
}
lockState <<= 1;
try {
if (t.getLockingKeyState(KeyEvent.VK_SCROLL_LOCK)) {
lockState++;
}
- } catch (java.lang.UnsupportedOperationException ex) {
+ } catch (UnsupportedOperationException ex) {
}
lockState <<= 1;
try {
if (t.getLockingKeyState(KeyEvent.VK_NUM_LOCK)) {
lockState++;
}
- } catch (java.lang.UnsupportedOperationException ex) {
+ } catch (UnsupportedOperationException ex) {
}
lockState <<= 1;
try {
if (t.getLockingKeyState(KeyEvent.VK_CAPS_LOCK)) {
lockState++;
}
- } catch (java.lang.UnsupportedOperationException ex) {
+ } catch (UnsupportedOperationException ex) {
}
return lockState;
}
@@ -434,7 +439,7 @@
* @param evt the key event to dispatch
*/
protected abstract void dispatchKeyEvent(KeyEvent evt);
-
+
/**
* Dispatches the specified AWT mouse event.
* @param evt the mouse event to dispatch
@@ -448,7 +453,7 @@
}
GraphicsNode node = root.nodeHitAt(gnp);
-
+
// If the receiving node has changed, send a notification
// check if we enter a new node
Point screenPos;
@@ -460,6 +465,8 @@
screenPos.y += evt.getY();
}
+ int currentLockState = getCurrentLockState();
+
if (lastHit != node) {
// post a MOUSE_EXITED event
if (lastHit != null) {
@@ -468,11 +475,11 @@
MOUSE_EXITED,
evt.getWhen(),
evt.getModifiers(),
- getCurrentLockState(),
+ currentLockState,
(float)gnp.getX(),
(float)gnp.getY(),
- (int)Math.floor(p.getX()),
- (int)Math.floor(p.getY()),
+ (int)Math.floor(p.getX()), // evt.getX() ??
+ (int)Math.floor(p.getY()), // evt.getY() ??
screenPos.x,
screenPos.y,
evt.getClickCount(),
@@ -486,9 +493,8 @@
MouseEvent.
MOUSE_ENTERED,
evt.getWhen(),
- evt.
- getModifiers(),
- getCurrentLockState(),
+ evt.getModifiers(),
+ currentLockState,
(float)gnp.getX(),
(float)gnp.getY(),
(int)Math.floor(p.getX()),
@@ -507,7 +513,7 @@
evt.getID(),
evt.getWhen(),
evt.getModifiers(),
- getCurrentLockState(),
+ currentLockState,
(float)gnp.getX(),
(float)gnp.getY(),
(int)Math.floor(p.getX()),
@@ -526,7 +532,7 @@
evt.getID(),
evt.getWhen(),
evt.getModifiers(),
- getCurrentLockState(),
+ currentLockState,
(float)gnp.getX(),
(float)gnp.getY(),
(int)Math.floor(p.getX()),
@@ -588,7 +594,7 @@
}
break;
default:
- throw new Error("Unknown Mouse Event type: "+evt.getID());
+ throw new IllegalArgumentException("Unknown Mouse Event type: "+evt.getID());
}
}
}
@@ -622,7 +628,7 @@
}
break;
default:
- throw new Error("Unknown Key Event type: "+evt.getID());
+ throw new IllegalArgumentException("Unknown Key Event type: "+evt.getID());
}
}
evt.consume();
@@ -630,12 +636,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.");
}
/**
@@ -670,11 +676,31 @@
* @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;
}
/**
@@ -682,11 +708,30 @@
* 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;
}
}