blob: 71d2532e36887c0e63433de33d069b3c231b48f7 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.draw2d.ui.render.awt.internal.svg;
import java.awt.Color;
import org.apache.batik.dom.svg.SVGOMDocument;
import org.apache.batik.svggen.SVGColor;
import org.apache.batik.svggen.SVGGeneratorContext;
import org.apache.batik.svggen.SVGPaintDescriptor;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.svg.SVGSVGElement;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.NodeIterator;
/**
* @author sshaw
*
* Utility class that will replace Black and white with corresponding outline and
* fill colors respectively.
*/
public class SVGColorConverter {
static private SVGColorConverter INSTANCE = new SVGColorConverter();
/**
* getInstance
* Implementation of the singleton pattern
*
* @return the Singleton Instance of SVGColorConverter
*/
static public SVGColorConverter getInstance() {
return INSTANCE;
}
/**
*
*/
private SVGColorConverter() {
super();
}
/**
* replaceDocumentColors
* Given an SVGOMDocument, this method will replace all fill, stroke and gradient
* colors with values that are based in. Black color will be replaced by the given
* outlineColor and White color will be replaced by the given fillColor.
*
* @param svgDoc SVGOMDocument to perform the replace on.
* @param fillColor This is the fill color that will replace all occurrences of white
* @param outlineColor This is the outline color that will replace all occurrences of black.
*/
public void replaceDocumentColors(SVGOMDocument svgDoc, Color fillColor, Color outlineColor) {
SVGSVGElement svgRoot = svgDoc.getRootElement();
NodeIterator ni = svgDoc.createNodeIterator(svgRoot, NodeFilter.SHOW_ALL, null, true);
Node node = ni.nextNode();
while (node != null) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element)node;
if (fillColor != null) {
setColorAttribute(svgDoc, element, SVGConstants.SVG_FILL_ATTRIBUTE, false, fillColor);
setColorAttribute(svgDoc, element, SVGConstants.SVG_STOP_COLOR_ATTRIBUTE, false, fillColor);
}
if (outlineColor != null) {
setColorAttribute(svgDoc, element, SVGConstants.SVG_STROKE_ATTRIBUTE, true, outlineColor);
setColorAttribute(svgDoc, element, SVGConstants.SVG_STOP_COLOR_ATTRIBUTE, true, outlineColor);
}
}
node = ni.nextNode();
}
}
public static final String SEMICOLON = ";"; //$NON-NLS-1$
public static final String COLON = ":"; //$NON-NLS-1$
private boolean isBlack(String color) {
String cleanColorStr = cleanFromSpaces(color);
return cleanColorStr.equals("#000000") || cleanColorStr.equalsIgnoreCase("BLACK") || cleanColorStr.equalsIgnoreCase("rgb(0,0,0)");//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
}
private boolean isWhite(String color) {
String cleanColorStr = cleanFromSpaces(color);
return cleanColorStr.equalsIgnoreCase("#FFFFFF") || cleanColorStr.equalsIgnoreCase("WHITE") || cleanColorStr.equalsIgnoreCase("rgb(255,255,255)");//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
}
private String cleanFromSpaces(String s) {
char [] chars = new char[s.length()];
int index = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != ' ') {
chars[index++] = s.charAt(i);
}
}
return new String(chars, 0, index);
}
/**
* setColorAttribute
* Utility function that will set the color attribute to the specified color
*
* @param element Element to set the attribute color of
* @param attributeName String attribute name, usually one of SVGConstants.SVG_FILL_ATTRIBUTE or
* SVGConstants.SVG_STROKE_ATTRIBUTE
* @param boolean black is true if replace with color, false to replace white.
* @param color Color to change the attribute to.
*/
protected void setColorAttribute(SVGOMDocument svgDoc, Element element, String attributeName, boolean black, Color color) {
SVGPaintDescriptor svgPD = SVGColor.toSVG(color, SVGGeneratorContext.createDefault(svgDoc));
if (element.hasAttribute(attributeName)) {
String value = element.getAttribute(attributeName);
// Only change the Stroke color if the current color is black
if( attributeName.equals(SVGConstants.SVG_STROKE_ATTRIBUTE) ||
attributeName.equals(SVGConstants.SVG_FILL_ATTRIBUTE)) {
if( (black && isBlack(value)) || (!black && isWhite(value)) ) {
element.setAttribute(attributeName, svgPD.getPaintValue());
}
}
}
else if (element.hasAttribute(SVGConstants.SVG_STYLE_TAG)) {
//TODO There must be a better way to set fill / outline color with the Batik libraries.
String style = element.getAttribute(SVGConstants.SVG_STYLE_TAG);
String preColor = ""; //$NON-NLS-1$
int nStart = style.indexOf(attributeName + COLON);
if (nStart != -1) {
if (nStart > 0)
preColor = style.substring(0, nStart);
String postColor = ""; //$NON-NLS-1$
int nEnd = style.indexOf(SEMICOLON, nStart);
if (nEnd == -1)
nEnd = style.length();
if (nEnd < style.length() - 1)
postColor = style.substring(nEnd + 1, style.length());
String currentColor = style.substring(nStart+attributeName.length() + 1, nEnd);
if( (black && isBlack(currentColor)) || (!black && isWhite(currentColor))) {
if (!currentColor.equals(SVGConstants.SVG_NONE_VALUE)) {
StringBuffer styleBuffer = new StringBuffer(style.length() + 5);
styleBuffer.append(preColor);
styleBuffer.append(" "); //$NON-NLS-1$
styleBuffer.append(attributeName);
styleBuffer.append(COLON);
styleBuffer.append(svgPD.getPaintValue());
if (!postColor.equals("")) { //$NON-NLS-1$
styleBuffer.append(SEMICOLON);
styleBuffer.append(postColor);
}
String styleNew = styleBuffer.toString();
element.setAttribute(SVGConstants.SVG_STYLE_TAG, styleNew);
}
}
}
}
}
}