package org.apache.batik.css.engine.value.svg;
import org.apache.batik.css.engine.CSSEngine;
import org.apache.batik.css.engine.CSSStylableElement;
import org.apache.batik.css.engine.StyleMap;
import org.apache.batik.css.engine.value.ListValue;
import org.apache.batik.css.engine.value.Value;
import org.apache.batik.css.engine.value.ValueManager;
import org.apache.batik.css.engine.value.svg12.CIELCHColor;
import org.apache.batik.css.engine.value.svg12.CIELabColor;
import org.apache.batik.css.engine.value.svg12.DeviceColor;
import org.apache.batik.css.engine.value.svg12.ICCNamedColor;
import org.apache.batik.util.CSSConstants;
import org.apache.batik.util.SVGTypes;
import org.w3c.css.sac.LexicalUnit;
import org.w3c.dom.DOMException;
import org.w3c.dom.css.CSSValue;
public class SVGColorManager extends ColorManager {
protected String property;
protected Value defaultValue;
public SVGColorManager(String prop) {
this(prop, SVGValueConstants.BLACK_RGB_VALUE);
}
public SVGColorManager(String prop, Value v) {
property = prop;
defaultValue = v;
}
public boolean isInheritedProperty() {
return false;
}
public boolean isAnimatableProperty() {
return true;
}
public boolean isAdditiveProperty() {
return true;
}
public int getPropertyType() {
return SVGTypes.TYPE_COLOR;
}
public String getPropertyName() {
return property;
}
public Value getDefaultValue() {
return defaultValue;
}
public Value createValue(LexicalUnit lu, CSSEngine engine)
throws DOMException {
if (lu.getLexicalUnitType() == LexicalUnit.SAC_IDENT) {
if (lu.getStringValue().equalsIgnoreCase
(CSSConstants.CSS_CURRENTCOLOR_VALUE)) {
return SVGValueConstants.CURRENTCOLOR_VALUE;
}
}
Value v = super.createValue(lu, engine);
lu = lu.getNextLexicalUnit();
if (lu == null) {
return v;
}
if (lu.getLexicalUnitType() != LexicalUnit.SAC_FUNCTION) {
throw createInvalidLexicalUnitDOMException
(lu.getLexicalUnitType());
}
ListValue result = new ListValue(' ');
result.append(v);
Value colorValue = parseColorFunction(lu, v);
if (colorValue != null) {
result.append(colorValue);
} else {
return v;
}
return result;
}
private Value parseColorFunction(LexicalUnit lu, Value v) {
String functionName = lu.getFunctionName();
if (functionName.equalsIgnoreCase(ICCColor.ICC_COLOR_FUNCTION)) {
return createICCColorValue(lu, v);
}
return parseColor12Function(lu, v);
}
private Value parseColor12Function(LexicalUnit lu, Value v) {
String functionName = lu.getFunctionName();
if (functionName.equalsIgnoreCase(ICCNamedColor.ICC_NAMED_COLOR_FUNCTION)) {
return createICCNamedColorValue(lu, v);
} else if (functionName.equalsIgnoreCase(CIELabColor.CIE_LAB_COLOR_FUNCTION)) {
return createCIELabColorValue(lu, v);
} else if (functionName.equalsIgnoreCase(CIELCHColor.CIE_LCH_COLOR_FUNCTION)) {
return createCIELCHColorValue(lu, v);
} else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_CMYK_COLOR_FUNCTION)) {
return createDeviceColorValue(lu, v, 4);
} else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_RGB_COLOR_FUNCTION)) {
return createDeviceColorValue(lu, v, 3);
} else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_GRAY_COLOR_FUNCTION)) {
return createDeviceColorValue(lu, v, 1);
} else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_NCHANNEL_COLOR_FUNCTION)) {
return createDeviceColorValue(lu, v, 0);
}
return null;
}
private Value createICCColorValue(LexicalUnit lu, Value v) {
lu = lu.getParameters();
expectIdent(lu);
ICCColor icc = new ICCColor(lu.getStringValue());
lu = lu.getNextLexicalUnit();
while (lu != null) {
expectComma(lu);
lu = lu.getNextLexicalUnit();
icc.append(getColorValue(lu));
lu = lu.getNextLexicalUnit();
}
return icc;
}
private Value createICCNamedColorValue(LexicalUnit lu, Value v) {
lu = lu.getParameters();
expectIdent(lu);
String profileName = lu.getStringValue();
lu = lu.getNextLexicalUnit();
expectComma(lu);
lu = lu.getNextLexicalUnit();
expectIdent(lu);
String colorName = lu.getStringValue();
ICCNamedColor icc = new ICCNamedColor(profileName, colorName);
lu = lu.getNextLexicalUnit();
return icc;
}
private Value createCIELabColorValue(LexicalUnit lu, Value v) {
lu = lu.getParameters();
float l = getColorValue(lu);
lu = lu.getNextLexicalUnit();
expectComma(lu);
lu = lu.getNextLexicalUnit();
float a = getColorValue(lu);
lu = lu.getNextLexicalUnit();
expectComma(lu);
lu = lu.getNextLexicalUnit();
float b = getColorValue(lu);
CIELabColor icc = new CIELabColor(l, a, b);
lu = lu.getNextLexicalUnit();
return icc;
}
private Value createCIELCHColorValue(LexicalUnit lu, Value v) {
lu = lu.getParameters();
float l = getColorValue(lu);
lu = lu.getNextLexicalUnit();
expectComma(lu);
lu = lu.getNextLexicalUnit();
float c = getColorValue(lu);
lu = lu.getNextLexicalUnit();
expectComma(lu);
lu = lu.getNextLexicalUnit();
float h = getColorValue(lu);
CIELCHColor icc = new CIELCHColor(l, c, h);
lu = lu.getNextLexicalUnit();
return icc;
}
private Value createDeviceColorValue(LexicalUnit lu, Value v, int expectedComponents) {
lu = lu.getParameters();
boolean nChannel = (expectedComponents <= 0);
DeviceColor col = new DeviceColor(nChannel);
col.append(getColorValue(lu));
LexicalUnit lastUnit = lu;
lu = lu.getNextLexicalUnit();
while (lu != null) {
expectComma(lu);
lu = lu.getNextLexicalUnit();
col.append(getColorValue(lu));
lastUnit = lu;
lu = lu.getNextLexicalUnit();
}
if (!nChannel && expectedComponents != col.getNumberOfColors()) {
throw createInvalidLexicalUnitDOMException(lastUnit.getLexicalUnitType());
}
return col;
}
private void expectIdent(LexicalUnit lu) {
if (lu.getLexicalUnitType() != LexicalUnit.SAC_IDENT) {
throw createInvalidLexicalUnitDOMException
(lu.getLexicalUnitType());
}
}
private void expectComma(LexicalUnit lu) {
if (lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
throw createInvalidLexicalUnitDOMException
(lu.getLexicalUnitType());
}
}
private void expectNonNull(LexicalUnit lu) {
if (lu == null) {
throw createInvalidLexicalUnitDOMException((short)-1);
}
}
public Value computeValue(CSSStylableElement elt,
String pseudo,
CSSEngine engine,
int idx,
StyleMap sm,
Value value) {
if (value == SVGValueConstants.CURRENTCOLOR_VALUE) {
sm.putColorRelative(idx, true);
int ci = engine.getColorIndex();
return engine.getComputedStyle(elt, pseudo, ci);
}
if (value.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
ListValue lv = (ListValue)value;
Value v = lv.item(0);
Value t = super.computeValue(elt, pseudo, engine, idx, sm, v);
if (t != v) {
ListValue result = new ListValue(' ');
result.append(t);
result.append(lv.item(1));
return result;
}
return value;
}
return super.computeValue(elt, pseudo, engine, idx, sm, value);
}
protected float getColorValue(LexicalUnit lu) {
expectNonNull(lu);
switch (lu.getLexicalUnitType()) {
case LexicalUnit.SAC_INTEGER:
return lu.getIntegerValue();
case LexicalUnit.SAC_REAL:
return lu.getFloatValue();
}
throw createInvalidLexicalUnitDOMException(lu.getLexicalUnitType());
}
}