package org.xmind.ui.internal.svgsupport;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.w3c.dom.Element;
public class SVGShapeInfoMap implements Cloneable {
private static final float DEFAULT_STROKE_LINEJOIN_MITER = 4.0f;
private static final float DEFAULT_STROKE_DASHOFFSET = 0f;
public static final int DEFAULT_STROKE_LINEJOIN = SWT.JOIN_MITER;
private static final float INVALID_FLOAT = -1f;
private static final float MAX_OPACITY = 1f;
private static final float MIN_OPACITY = 0f;
public static final String ID = "id"; //$NON-NLS-1$
public static final String FILL = "fill"; //$NON-NLS-1$
public static final String FILL_RULE = "fill-rule"; //$NON-NLS-1$
public static final String FILL_OPACITY = "fill-opacity"; //$NON-NLS-1$
public static final String STROKE = "stroke"; //$NON-NLS-1$
public static final String STROKE_WIDTH = "stroke-width"; //$NON-NLS-1$
public static final String STROKE_OPACITY = "stroke-opacity"; //$NON-NLS-1$
public static final String STROKE_LINESTYLE = "line-style"; //$NON-NLS-1$
public static final String STROKE_LINECAP = "stroke-linecap"; //$NON-NLS-1$
// line cap: butt | round | square
public static final String STROKE_LINECAP_BUTT = "butt"; //$NON-NLS-1$
public static final String STROKE_LINECAP_ROUND = "round"; //$NON-NLS-1$
public static final String STROKE_LINECAP_SQUARE = "square"; //$NON-NLS-1$
public static final String STROKE_DASHARRAY = "stroke-dasharray"; //$NON-NLS-1$
public static final String STROKE_LINEJOIN = "stroke-linejoin"; //$NON-NLS-1$
// line join : miter | round | bevel
public static final String STROKE_LINEJOIN_MITER = "miter"; //$NON-NLS-1$
public static final String STROKE_LINEJOIN_ROUND = "round"; //$NON-NLS-1$
public static final String STROKE_LINEJOIN_BEVEL = "bevel"; //$NON-NLS-1$
public static final String STROKE_MITERLIMIT = "stroke-miterlimit"; //$NON-NLS-1$
public static final String STROKE_DASHOFFSET = "stroke-dashoffset"; //$NON-NLS-1$
public static final String FILL_RULE_EVENODD_STRING = "evenodd"; //$NON-NLS-1$
public static final String FILL_RULE_NONZERO_STRING = "nonzero"; //$NON-NLS-1$
public static final String TRANSFORM = "transform"; //$NON-NLS-1$
private static final String NONE = "none"; //$NON-NLS-1$
private Map<String, Object> map = new HashMap<String, Object>();
private int idCount = 0;
void parse(Element implementation, SVGShapeInfoMap infoMap) {
if (infoMap != null) {
map.putAll(infoMap.map);
map.remove(TRANSFORM);
}
if (implementation.hasAttribute(ID))
putId(implementation.getAttribute(ID));
else
putId(generateRandomId());
parseStyles(implementation);
}
private synchronized String generateRandomId() {
return "shapeId-" + (idCount++); //$NON-NLS-1$
}
private void parseStyles(Element implementation) {
//FIXME don't handle the style format : style(a:b,c:d)
parseFillStyle(implementation);
parseStrokeStyle(implementation);
parseLineAttributes(implementation);
parseTransformStyle(implementation);
}
private void parseFillStyle(Element implementation) {
String fill = implementation.getAttribute(FILL);
if (implementation.hasAttribute(FILL) && !fill.equals(NONE)) {
SVGColor color = ColorRecognizer.recognizeColor(fill,
SVGShape.idRefs);
if (color != null)
putFillColor(color);
}
if (implementation.hasAttribute(FILL_RULE))
putFillRule(implementation.getAttribute(FILL_RULE));
float opacity = getFloatAttribute(implementation, FILL_OPACITY);
if (opacity != INVALID_FLOAT)
putFillOpacity(opacity * getFillOpacity());
}
private void parseStrokeStyle(Element implementation) {
String stroke = implementation.getAttribute(STROKE).trim();
if (implementation.hasAttribute(STROKE) || !stroke.equals(NONE)) {
SVGColor color = ColorRecognizer.recognizeColor(stroke,
SVGShape.idRefs);
if (color != null)
putStrokeColor(color);
}
float width = getFloatAttribute(implementation, STROKE_WIDTH);
if (0 <= width)
putLineWidth(width);
float opacity = getFloatAttribute(implementation, STROKE_OPACITY);
if (MIN_OPACITY <= opacity && MAX_OPACITY >= opacity)
putStrokeOpacity(opacity * getStrokeOpacity());
}
private void parseLineAttributes(Element implementation) {
if (implementation.hasAttribute(STROKE_LINECAP)) {
String lineCap = implementation.getAttribute(STROKE_LINECAP);
if (lineCap.equals(STROKE_LINECAP_ROUND)) {
putLineCap(SWT.CAP_ROUND);
} else if (lineCap.equals(STROKE_LINECAP_SQUARE)) {
putLineCap(SWT.CAP_SQUARE);
}
}
if (implementation.hasAttribute(STROKE_DASHARRAY)) {
String dashArray = implementation.getAttribute(STROKE_DASHARRAY)
.trim();
String[] strs = dashArray.split("[\\,|\\s]+"); //$NON-NLS-1$
float[] dashArr = new float[strs.length];
for (int i = 0; i < strs.length; i++)
dashArr[i] = Float.valueOf(strs[i]);
putLineDash(dashArr);
}
if (implementation.hasAttribute(STROKE_DASHOFFSET)) {
String dashOffset = implementation.getAttribute(STROKE_DASHOFFSET);
putLineDashOffSET(Float.valueOf(dashOffset));
}
if (implementation.hasAttribute(STROKE_LINEJOIN)) {
String lineJoin = implementation.getAttribute(STROKE_LINEJOIN);
if (lineJoin.equals(STROKE_LINEJOIN_ROUND))
putLineJoin(SWT.JOIN_ROUND);
else if (lineJoin.equals(STROKE_LINEJOIN_BEVEL))
putLineJoin(SWT.JOIN_BEVEL);
}
if (implementation.hasAttribute(STROKE_MITERLIMIT)) {
String miterLimit = implementation.getAttribute(STROKE_MITERLIMIT);
putLineMiterLimit(Float.valueOf(miterLimit));
}
}
private void parseTransformStyle(Element implementation) {
SVGTransform svgTransform = new SVGTransform();
if (implementation.hasAttribute(TRANSFORM)) {
String transform = implementation.getAttribute(TRANSFORM).trim();
svgTransform.parseTransform(transform);
putTransform(svgTransform);
}
}
float getFloatAttribute(Element ele, String name) {
if (ele.hasAttribute(name))
return Float.valueOf(ele.getAttribute(name));
return INVALID_FLOAT;
}
@Override
protected SVGShapeInfoMap clone() {
Map<String, Object> map = new HashMap<String, Object>();
map.putAll(map);
SVGShapeInfoMap infoMap = new SVGShapeInfoMap();
infoMap.map = map;
return infoMap;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SVGShapeInfoMap && getId() != null) {
return getId().equals(((SVGShapeInfoMap) obj).getId());
}
return false;
}
@Override
public int hashCode() {
return map.hashCode();
}
@Override
public String toString() {
return " style:id=" + getId() + " "; //$NON-NLS-1$ //$NON-NLS-2$
}
public void add(SVGShapeInfoMap info) {
for (String key : info.map.keySet()) {
if (!map.containsKey(key) && !key.equals(TRANSFORM)) {
map.put(key, info.map.get(key));
} else {
if (key.equals(FILL_OPACITY))
map.put(FILL_OPACITY,
getFillOpacity() * info.getFillOpacity());
if (key.equals(STROKE_OPACITY))
map.put(STROKE_OPACITY,
getStrokeOpacity() * info.getStrokeOpacity());
}
}
}
public String getId() {
return (String) map.get(ID);
}
public void putId(String id) {
map.put(ID, id);
}
public SVGColor getFillColor() {
return (SVGColor) map.get(FILL);
}
public void putFillColor(SVGColor fillColor) {
map.put(FILL, fillColor);
}
public String getFillRule() {
Object obj = map.get(FILL_RULE);
if (obj == null)
return FILL_RULE_NONZERO_STRING;
return (String) obj;
}
public void putFillRule(String fillRule) {
map.put(FILL_RULE, fillRule);
}
public float getFillOpacity() {
Object obj = map.get(FILL_OPACITY);
float opacity = MAX_OPACITY;
if (obj != null)
opacity = (Float) obj;
return opacity;
}
public void putFillOpacity(float fillOpacity) {
map.put(FILL_OPACITY, fillOpacity);
}
public SVGColor getStrokeColor() {
return (SVGColor) map.get(STROKE);
}
public void putStrokeColor(SVGColor strokeColor) {
map.put(STROKE, strokeColor);
}
public float getLineWidth() {
Object obj = map.get(STROKE_WIDTH);
float lineWidth = 1.0f;
if (obj != null)
lineWidth = (Float) obj;
return lineWidth;
}
public void putLineWidth(float lineWidth) {
map.put(STROKE_WIDTH, lineWidth);
}
public float getStrokeOpacity() {
Object obj = map.get(STROKE_OPACITY);
float opacity = MAX_OPACITY;
if (obj != null)
opacity = (Float) obj;
return opacity;
}
public void putStrokeOpacity(float strokeOpacity) {
map.put(STROKE_OPACITY, strokeOpacity);
}
public int getLineStyle() {
Object obj = map.get(STROKE_LINESTYLE);
if (obj == null)
return SWT.LINE_CUSTOM;
else
return (Integer) obj;
}
public void putLineStyle(int style) {
map.put(STROKE_LINESTYLE, style);
}
public int getLineCap() {
Object obj = map.get(STROKE_LINECAP);
if (obj == null)
return SWT.CAP_FLAT;
else
return (Integer) obj;
}
public void putLineCap(int lineCap) {
map.put(STROKE_LINECAP, lineCap);
}
public float[] getLineDash() {
if (map.get(STROKE_DASHARRAY) == null)
return null;
else
return (float[]) map.get(STROKE_DASHARRAY);
}
public void putLineDash(float[] lineDash) {
map.put(STROKE_DASHARRAY, lineDash);
}
public int getLineJoin() {
Object obj = map.get(STROKE_LINEJOIN);
if (obj == null)
return DEFAULT_STROKE_LINEJOIN;
else
return (Integer) obj;
}
public void putLineJoin(int lineJoin) {
map.put(STROKE_LINEJOIN, lineJoin);
}
public float getLineMiterLimit() {
Object obj = map.get(STROKE_LINEJOIN_MITER);
if (obj == null)
return DEFAULT_STROKE_LINEJOIN_MITER;
else
return (Float) obj;
}
public void putLineMiterLimit(float lineMiterLimit) {
map.put(STROKE_LINEJOIN_MITER, lineMiterLimit);
}
public float getLineDashOffset() {
Object obj = map.get(STROKE_DASHOFFSET);
if (obj == null)
return DEFAULT_STROKE_DASHOFFSET;
else
return (Integer) obj;
}
public void putLineDashOffSET(float lineDashOffput) {
map.put(STROKE_DASHOFFSET, lineDashOffput);
}
public SVGTransform getTransform() {
return (SVGTransform) map.get(TRANSFORM);
}
public void putTransform(SVGTransform transform) {
map.put(TRANSFORM, transform);
}
}