1
19 package org.apache.batik.css.engine.value.svg;
20
21 import org.apache.batik.css.engine.CSSEngine;
22 import org.apache.batik.css.engine.CSSStylableElement;
23 import org.apache.batik.css.engine.StyleMap;
24 import org.apache.batik.css.engine.value.ListValue;
25 import org.apache.batik.css.engine.value.Value;
26 import org.apache.batik.css.engine.value.ValueManager;
27 import org.apache.batik.css.engine.value.svg12.CIELCHColor;
28 import org.apache.batik.css.engine.value.svg12.CIELabColor;
29 import org.apache.batik.css.engine.value.svg12.DeviceColor;
30 import org.apache.batik.css.engine.value.svg12.ICCNamedColor;
31 import org.apache.batik.util.CSSConstants;
32 import org.apache.batik.util.SVGTypes;
33
34 import org.w3c.css.sac.LexicalUnit;
35 import org.w3c.dom.DOMException;
36 import org.w3c.dom.css.CSSValue;
37
38
44 public class SVGColorManager extends ColorManager {
45
46
49 protected String property;
50
51
54 protected Value defaultValue;
55
56
60 public SVGColorManager(String prop) {
61 this(prop, SVGValueConstants.BLACK_RGB_VALUE);
62 }
63
64
67 public SVGColorManager(String prop, Value v) {
68 property = prop;
69 defaultValue = v;
70 }
71
72
75 public boolean isInheritedProperty() {
76 return false;
77 }
78
79
82 public boolean isAnimatableProperty() {
83 return true;
84 }
85
86
89 public boolean isAdditiveProperty() {
90 return true;
91 }
92
93
96 public int getPropertyType() {
97 return SVGTypes.TYPE_COLOR;
98 }
99
100
103 public String getPropertyName() {
104 return property;
105 }
106
107
108
112 public Value getDefaultValue() {
113 return defaultValue;
114 }
115
116
119 public Value createValue(LexicalUnit lu, CSSEngine engine)
120 throws DOMException {
121 if (lu.getLexicalUnitType() == LexicalUnit.SAC_IDENT) {
122 if (lu.getStringValue().equalsIgnoreCase
123 (CSSConstants.CSS_CURRENTCOLOR_VALUE)) {
124 return SVGValueConstants.CURRENTCOLOR_VALUE;
125 }
126 }
127 Value v = super.createValue(lu, engine);
128 lu = lu.getNextLexicalUnit();
129 if (lu == null) {
130 return v;
131 }
132
133
134 if (lu.getLexicalUnitType() != LexicalUnit.SAC_FUNCTION) {
135 throw createInvalidLexicalUnitDOMException
136 (lu.getLexicalUnitType());
137 }
138
139 ListValue result = new ListValue(' ');
140 result.append(v);
141
142 Value colorValue = parseColorFunction(lu, v);
143 if (colorValue != null) {
144 result.append(colorValue);
145 } else {
146 return v;
147 }
148 return result;
149 }
150
151 private Value parseColorFunction(LexicalUnit lu, Value v) {
152 String functionName = lu.getFunctionName();
153 if (functionName.equalsIgnoreCase(ICCColor.ICC_COLOR_FUNCTION)) {
154 return createICCColorValue(lu, v);
155 }
156 return parseColor12Function(lu, v);
157 }
158
159 private Value parseColor12Function(LexicalUnit lu, Value v) {
160 String functionName = lu.getFunctionName();
161 if (functionName.equalsIgnoreCase(ICCNamedColor.ICC_NAMED_COLOR_FUNCTION)) {
162 return createICCNamedColorValue(lu, v);
163 } else if (functionName.equalsIgnoreCase(CIELabColor.CIE_LAB_COLOR_FUNCTION)) {
164 return createCIELabColorValue(lu, v);
165 } else if (functionName.equalsIgnoreCase(CIELCHColor.CIE_LCH_COLOR_FUNCTION)) {
166 return createCIELCHColorValue(lu, v);
167 } else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_CMYK_COLOR_FUNCTION)) {
168 return createDeviceColorValue(lu, v, 4);
169 } else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_RGB_COLOR_FUNCTION)) {
170 return createDeviceColorValue(lu, v, 3);
171 } else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_GRAY_COLOR_FUNCTION)) {
172 return createDeviceColorValue(lu, v, 1);
173 } else if (functionName.equalsIgnoreCase(DeviceColor.DEVICE_NCHANNEL_COLOR_FUNCTION)) {
174 return createDeviceColorValue(lu, v, 0);
175 }
176 return null;
177 }
178
179 private Value createICCColorValue(LexicalUnit lu, Value v) {
180 lu = lu.getParameters();
181 expectIdent(lu);
182
183 ICCColor icc = new ICCColor(lu.getStringValue());
184
185 lu = lu.getNextLexicalUnit();
186 while (lu != null) {
187 expectComma(lu);
188 lu = lu.getNextLexicalUnit();
189 icc.append(getColorValue(lu));
190 lu = lu.getNextLexicalUnit();
191 }
192 return icc;
193 }
194
195 private Value createICCNamedColorValue(LexicalUnit lu, Value v) {
196 lu = lu.getParameters();
197 expectIdent(lu);
198 String profileName = lu.getStringValue();
199
200 lu = lu.getNextLexicalUnit();
201 expectComma(lu);
202 lu = lu.getNextLexicalUnit();
203 expectIdent(lu);
204 String colorName = lu.getStringValue();
205
206 ICCNamedColor icc = new ICCNamedColor(profileName, colorName);
207
208 lu = lu.getNextLexicalUnit();
209 return icc;
210 }
211
212 private Value createCIELabColorValue(LexicalUnit lu, Value v) {
213 lu = lu.getParameters();
214 float l = getColorValue(lu);
215 lu = lu.getNextLexicalUnit();
216 expectComma(lu);
217 lu = lu.getNextLexicalUnit();
218 float a = getColorValue(lu);
219 lu = lu.getNextLexicalUnit();
220 expectComma(lu);
221 lu = lu.getNextLexicalUnit();
222 float b = getColorValue(lu);
223
224 CIELabColor icc = new CIELabColor(l, a, b);
225
226 lu = lu.getNextLexicalUnit();
227 return icc;
228 }
229
230 private Value createCIELCHColorValue(LexicalUnit lu, Value v) {
231 lu = lu.getParameters();
232 float l = getColorValue(lu);
233 lu = lu.getNextLexicalUnit();
234 expectComma(lu);
235 lu = lu.getNextLexicalUnit();
236 float c = getColorValue(lu);
237 lu = lu.getNextLexicalUnit();
238 expectComma(lu);
239 lu = lu.getNextLexicalUnit();
240 float h = getColorValue(lu);
241
242 CIELCHColor icc = new CIELCHColor(l, c, h);
243
244 lu = lu.getNextLexicalUnit();
245 return icc;
246 }
247
248 private Value createDeviceColorValue(LexicalUnit lu, Value v, int expectedComponents) {
249 lu = lu.getParameters();
250
251 boolean nChannel = (expectedComponents <= 0);
252 DeviceColor col = new DeviceColor(nChannel);
253
254 col.append(getColorValue(lu));
255 LexicalUnit lastUnit = lu;
256 lu = lu.getNextLexicalUnit();
257 while (lu != null) {
258 expectComma(lu);
259 lu = lu.getNextLexicalUnit();
260 col.append(getColorValue(lu));
261 lastUnit = lu;
262 lu = lu.getNextLexicalUnit();
263 }
264 if (!nChannel && expectedComponents != col.getNumberOfColors()) {
265 throw createInvalidLexicalUnitDOMException(lastUnit.getLexicalUnitType());
266 }
267 return col;
268 }
269
270 private void expectIdent(LexicalUnit lu) {
271 if (lu.getLexicalUnitType() != LexicalUnit.SAC_IDENT) {
272 throw createInvalidLexicalUnitDOMException
273 (lu.getLexicalUnitType());
274 }
275 }
276
277 private void expectComma(LexicalUnit lu) {
278 if (lu.getLexicalUnitType() != LexicalUnit.SAC_OPERATOR_COMMA) {
279 throw createInvalidLexicalUnitDOMException
280 (lu.getLexicalUnitType());
281 }
282 }
283
284 private void expectNonNull(LexicalUnit lu) {
285 if (lu == null) {
286 throw createInvalidLexicalUnitDOMException((short)-1);
287 }
288 }
289
290
294 public Value computeValue(CSSStylableElement elt,
295 String pseudo,
296 CSSEngine engine,
297 int idx,
298 StyleMap sm,
299 Value value) {
300 if (value == SVGValueConstants.CURRENTCOLOR_VALUE) {
301 sm.putColorRelative(idx, true);
302
303 int ci = engine.getColorIndex();
304 return engine.getComputedStyle(elt, pseudo, ci);
305 }
306 if (value.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
307 ListValue lv = (ListValue)value;
308 Value v = lv.item(0);
309 Value t = super.computeValue(elt, pseudo, engine, idx, sm, v);
310 if (t != v) {
311 ListValue result = new ListValue(' ');
312 result.append(t);
313 result.append(lv.item(1));
314 return result;
315 }
316 return value;
317 }
318 return super.computeValue(elt, pseudo, engine, idx, sm, value);
319 }
320
321
324 protected float getColorValue(LexicalUnit lu) {
325 expectNonNull(lu);
326 switch (lu.getLexicalUnitType()) {
327 case LexicalUnit.SAC_INTEGER:
328 return lu.getIntegerValue();
329 case LexicalUnit.SAC_REAL:
330 return lu.getFloatValue();
331 }
332 throw createInvalidLexicalUnitDOMException(lu.getLexicalUnitType());
333 }
334 }
335