1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jeuclid.elements.support.attributes;
20
21 import java.awt.Color;
22 import java.util.HashMap;
23 import java.util.Locale;
24 import java.util.Map;
25 import java.util.StringTokenizer;
26
27 import net.sourceforge.jeuclid.Constants;
28 import net.sourceforge.jeuclid.LayoutContext;
29 import net.sourceforge.jeuclid.elements.AbstractJEuclidElement;
30 import net.sourceforge.jeuclid.elements.support.GraphicsSupport;
31 import net.sourceforge.jeuclid.elements.support.operatordict.OperatorDictionary;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36
37
38
39
40
41 public final class AttributesHelper {
42
43
44
45
46 public static final String COLOR_TRANSPARENT = "transparent";
47
48
49
50
51 public static final String VERYVERYTHINMATHSPACE = "0.0555556em";
52
53
54
55
56 public static final String VERYTHINMATHSPACE = "0.111111em";
57
58
59
60
61 public static final String THINMATHSPACE = "0.166667em";
62
63
64
65
66 public static final String MEDIUMMATHSPACE = "0.222222em";
67
68
69
70
71 public static final String THICKMATHSPACE = "0.277778em";
72
73
74
75
76 public static final String VERYTHICKMATHSPACE = "0.333333em";
77
78
79
80
81 public static final String VERYVERYTHICKMATHSPACE = "0.388889em";
82
83
84
85
86 public static final String PT = "pt";
87
88
89
90
91 public static final String INFINITY = "9999999pt";
92
93 private static final String ERROR_PARSING_NUMBER = "Error Parsing number: ";
94
95 private static final int HASHSHORT_ALPHA = 5;
96
97 private static final int HASHSHORT_NO_ALPHA = 4;
98
99 private static final int SHORT_INDEX_RED = 1;
100
101 private static final int SHORT_INDEX_GREEN = 2;
102
103 private static final int SHORT_INDEX_BLUE = 3;
104
105 private static final int HASHLEN_ALPHA = 9;
106
107 private static final int HASHLEN_NO_ALPHA = 7;
108
109 private static final int HEXBASE = 16;
110
111 private static final float MAX_HEXCHAR_AS_FLOAT = 15f;
112
113 private static final int MAX_BYTE = 255;
114
115 private static final float MAX_PERCENT_AS_FLOAT = 100.0f;
116
117 private static final float MAX_BYTE_AS_FLOAT = 255f;
118
119 private static final String PERCENT_SIGN = "%";
120
121 private static final String COMMA = ",";
122
123
124
125
126
127
128
129
130 private static final float EM = 0.83888888888888888888f;
131
132
133
134
135
136
137
138
139 private static final float EX = 0.5f;
140
141
142
143
144 private static final float DPI = 72.0f;
145
146 private static final float PERCENT = 0.01f;
147
148 private static final float CM_PER_INCH = 2.54f;
149
150 private static final float MM_PER_INCH = AttributesHelper.CM_PER_INCH * 10.0f;
151
152 private static final float PT_PER_PC = 12.0f;
153
154 private static final Map<String, String> SIZETRANSLATIONS = new HashMap<String, String>();
155
156 private static final Map<String, Float> RELATIVE_UNITS = new HashMap<String, Float>();
157
158 private static final Map<String, Float> ABSOLUTE_UNITS = new HashMap<String, Float>();
159
160 private static final Map<String, Color> COLOR_MAPPINGS = new HashMap<String, Color>();
161
162
163
164
165 private static final Log LOGGER = LogFactory
166 .getLog(AbstractJEuclidElement.class);
167
168
169
170
171
172 private AttributesHelper() {
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186 public static float parseRelativeSize(final String sizeString,
187 final LayoutContext context, final float relativeTo) {
188 if (sizeString == null) {
189 return relativeTo;
190 }
191 final String tSize = AttributesHelper.prepareSizeString(sizeString);
192 float retVal;
193 try {
194 if (tSize.length() >= 2) {
195 final int valueLen = tSize.length() - 2;
196 final String unit = tSize.substring(valueLen);
197 final float value = Float.parseFloat(tSize.substring(0,
198 valueLen));
199 if (AttributesHelper.ABSOLUTE_UNITS.containsKey(unit)) {
200 retVal = AttributesHelper.convertSizeToPt(sizeString,
201 context, AttributesHelper.PT);
202 } else if (AttributesHelper.RELATIVE_UNITS.containsKey(unit)) {
203 retVal = value * relativeTo
204 * AttributesHelper.RELATIVE_UNITS.get(unit);
205 } else {
206 retVal = Float.parseFloat(tSize) * relativeTo;
207 }
208 } else {
209 retVal = Float.parseFloat(tSize) * relativeTo;
210 }
211 } catch (final NumberFormatException nfe) {
212 retVal = relativeTo;
213 AttributesHelper.LOGGER.warn(AttributesHelper.ERROR_PARSING_NUMBER
214 + sizeString);
215 }
216 return retVal;
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231 public static float convertSizeToPt(final String sizeString,
232 final LayoutContext context, final String defaultUnit) {
233 final String tSize = AttributesHelper.prepareSizeString(sizeString);
234 if (tSize.length() == 0) {
235 return 0;
236 }
237 float retVal;
238 try {
239 final String unit;
240 final float value;
241 if (tSize.length() <= 2) {
242 unit = defaultUnit;
243 value = Float.parseFloat(tSize);
244 } else {
245 final int valueLen = tSize.length() - 2;
246 unit = tSize.substring(valueLen);
247 value = Float.parseFloat(tSize.substring(0, valueLen));
248 }
249 if (value == 0) {
250 retVal = 0.0f;
251 } else if (AttributesHelper.RELATIVE_UNITS.containsKey(unit)) {
252 retVal = value * GraphicsSupport.getFontsizeInPoint(context)
253 * AttributesHelper.RELATIVE_UNITS.get(unit);
254 } else if (AttributesHelper.ABSOLUTE_UNITS.containsKey(unit)) {
255 retVal = value * AttributesHelper.ABSOLUTE_UNITS.get(unit);
256 } else if (defaultUnit.length() > 0) {
257 retVal = AttributesHelper.convertSizeToPt(sizeString
258 + defaultUnit, context, "");
259 } else {
260 retVal = Float.parseFloat(tSize);
261 AttributesHelper.LOGGER.warn("Error Parsing attribute: "
262 + sizeString + " assuming " + retVal
263 + AttributesHelper.PT);
264 }
265 } catch (final NumberFormatException nfe) {
266 retVal = 1.0f;
267 AttributesHelper.LOGGER.warn(AttributesHelper.ERROR_PARSING_NUMBER
268 + sizeString + " falling back to " + retVal
269 + AttributesHelper.PT);
270 }
271 return retVal;
272 }
273
274 private static String prepareSizeString(final String sizeString) {
275 if (sizeString == null) {
276 return "";
277 }
278 String tSize = sizeString.trim().toLowerCase(Locale.ENGLISH);
279
280 final String translatesTo = AttributesHelper.SIZETRANSLATIONS
281 .get(tSize);
282 if (translatesTo != null) {
283 tSize = translatesTo;
284 }
285 if (tSize.endsWith(AttributesHelper.PERCENT_SIGN)) {
286
287 tSize = new StringBuilder(tSize).append(' ').toString();
288 }
289 return tSize;
290 }
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314 public static Color stringToColor(final String value,
315 final Color defaultValue) {
316 if (value == null) {
317 return null;
318 }
319
320 final String lowVal = value.toLowerCase(Locale.ENGLISH);
321 Color parsedColor = null;
322
323 if (AttributesHelper.COLOR_MAPPINGS.containsKey(lowVal)) {
324 parsedColor = AttributesHelper.COLOR_MAPPINGS.get(lowVal);
325 } else {
326 if (value.charAt(0) == '#') {
327 parsedColor = AttributesHelper.parseWithHash(value);
328 } else if (value.startsWith("rgb(")) {
329 parsedColor = AttributesHelper.parseAsRGB(value);
330 } else if (value.startsWith("java.awt.Color")) {
331 parsedColor = AttributesHelper.parseAsJavaAWTColor(value);
332 }
333
334 if (parsedColor == null) {
335 parsedColor = defaultValue;
336 }
337
338 if (parsedColor != null) {
339 AttributesHelper.COLOR_MAPPINGS.put(value, parsedColor);
340 }
341 }
342 return parsedColor;
343 }
344
345
346
347
348
349
350
351
352
353 private static Color parseAsJavaAWTColor(final String value) {
354 final Color parsedColor;
355 final int poss = value.indexOf('[');
356 final int pose = value.indexOf(']');
357 if ((poss == -1) || (pose == -1)) {
358 parsedColor = null;
359 } else {
360 parsedColor = AttributesHelper.parseCommaSeparatedString(value
361 .substring(poss + 1, pose));
362 }
363 return parsedColor;
364 }
365
366
367
368
369
370
371
372
373 private static Color parseAsRGB(final String value) {
374 final Color parsedColor;
375 final int poss = value.indexOf('(');
376 final int pose = value.indexOf(')');
377 if ((poss == -1) || (pose == -1)) {
378 parsedColor = null;
379 } else {
380 parsedColor = AttributesHelper.parseCommaSeparatedString(value
381 .substring(poss + 1, pose));
382 }
383 return parsedColor;
384 }
385
386 private static Color parseCommaSeparatedString(final String value) {
387 Color parsedColor;
388 final StringTokenizer st = new StringTokenizer(value,
389 AttributesHelper.COMMA);
390 try {
391 float red = 0.0f;
392 float green = 0.0f;
393 float blue = 0.0f;
394 if (st.hasMoreTokens()) {
395 final String str = st.nextToken().trim();
396 red = AttributesHelper.parseFloatOrPercent(str);
397 }
398 if (st.hasMoreTokens()) {
399 final String str = st.nextToken().trim();
400 green = AttributesHelper.parseFloatOrPercent(str);
401 }
402 if (st.hasMoreTokens()) {
403 final String str = st.nextToken().trim();
404 blue = AttributesHelper.parseFloatOrPercent(str);
405 }
406 parsedColor = new Color(red, green, blue);
407 } catch (final NumberFormatException e) {
408 AttributesHelper.LOGGER.warn(e);
409 parsedColor = null;
410 }
411 return parsedColor;
412 }
413
414 private static float parseFloatOrPercent(final String str) {
415 final float value;
416 if (str.endsWith(AttributesHelper.PERCENT_SIGN)) {
417 value = Float.parseFloat(str.substring(0, str.length() - 1))
418 / AttributesHelper.MAX_PERCENT_AS_FLOAT;
419 } else {
420 value = Float.parseFloat(str) / AttributesHelper.MAX_BYTE_AS_FLOAT;
421 }
422 if ((value < 0.0f) || (value > 1.0f)) {
423 throw new NumberFormatException(str + " is out of Range");
424 }
425 return value;
426 }
427
428
429
430
431
432
433
434
435 private static Color parseWithHash(final String value) {
436 Color parsedColor = null;
437 try {
438 final int len = value.length();
439 if ((len >= AttributesHelper.HASHSHORT_NO_ALPHA)
440 && (len <= AttributesHelper.HASHSHORT_ALPHA)) {
441
442 final float red = Integer.parseInt(value.substring(
443 AttributesHelper.SHORT_INDEX_RED,
444 AttributesHelper.SHORT_INDEX_RED + 1),
445 AttributesHelper.HEXBASE)
446 / AttributesHelper.MAX_HEXCHAR_AS_FLOAT;
447 final float green = Integer.parseInt(value.substring(
448 AttributesHelper.SHORT_INDEX_GREEN,
449 AttributesHelper.SHORT_INDEX_GREEN + 1),
450 AttributesHelper.HEXBASE)
451 / AttributesHelper.MAX_HEXCHAR_AS_FLOAT;
452 final float blue = Integer.parseInt(value.substring(
453 AttributesHelper.SHORT_INDEX_BLUE,
454 AttributesHelper.SHORT_INDEX_BLUE + 1),
455 AttributesHelper.HEXBASE)
456 / AttributesHelper.MAX_HEXCHAR_AS_FLOAT;
457 float alpha = 1.0f;
458 if (len == AttributesHelper.HASHSHORT_ALPHA) {
459 alpha = Integer.parseInt(value
460 .substring(AttributesHelper.HASHSHORT_NO_ALPHA),
461 AttributesHelper.HEXBASE)
462 / AttributesHelper.MAX_HEXCHAR_AS_FLOAT;
463 }
464 parsedColor = new Color(red, green, blue, alpha);
465 } else if ((len == AttributesHelper.HASHLEN_NO_ALPHA)
466 || (len == AttributesHelper.HASHLEN_ALPHA)) {
467 final int red = Integer.parseInt(value.substring(1, 3),
468 AttributesHelper.HEXBASE);
469 final int green = Integer.parseInt(value.substring(3, 5),
470 AttributesHelper.HEXBASE);
471 final int blue = Integer.parseInt(value.substring(5,
472 AttributesHelper.HASHLEN_NO_ALPHA),
473 AttributesHelper.HEXBASE);
474 int alpha = AttributesHelper.MAX_BYTE;
475 if (len == AttributesHelper.HASHLEN_ALPHA) {
476 alpha = Integer.parseInt(value
477 .substring(AttributesHelper.HASHLEN_NO_ALPHA),
478 AttributesHelper.HEXBASE);
479 }
480 parsedColor = new Color(red, green, blue, alpha);
481 } else {
482 throw new NumberFormatException();
483 }
484 } catch (final NumberFormatException e) {
485 return null;
486 }
487 return parsedColor;
488 }
489
490
491
492
493
494
495
496
497
498
499
500 public static String colorTOsRGBString(final Color color) {
501 if (color == null) {
502 return AttributesHelper.COLOR_TRANSPARENT;
503 }
504 final StringBuffer sbuf = new StringBuffer(10);
505 sbuf.append('#');
506 String s = Integer.toHexString(color.getRed());
507 if (s.length() == 1) {
508 sbuf.append('0');
509 }
510 sbuf.append(s);
511 s = Integer.toHexString(color.getGreen());
512 if (s.length() == 1) {
513 sbuf.append('0');
514 }
515 sbuf.append(s);
516 s = Integer.toHexString(color.getBlue());
517 if (s.length() == 1) {
518 sbuf.append('0');
519 }
520 sbuf.append(s);
521 if (color.getAlpha() != AttributesHelper.MAX_BYTE) {
522 s = Integer.toHexString(color.getAlpha());
523 if (s.length() == 1) {
524 sbuf.append('0');
525 }
526 sbuf.append(s);
527 }
528 return sbuf.toString();
529
530 }
531
532
533 static {
534
535
536 AttributesHelper.SIZETRANSLATIONS.put(
537 OperatorDictionary.NAME_VERYVERYTHINMATHSPACE,
538 AttributesHelper.VERYVERYTHINMATHSPACE);
539 AttributesHelper.SIZETRANSLATIONS.put(
540 OperatorDictionary.NAME_VERYTHINMATHSPACE,
541 AttributesHelper.VERYTHINMATHSPACE);
542 AttributesHelper.SIZETRANSLATIONS.put(
543 OperatorDictionary.NAME_THINMATHSPACE,
544 AttributesHelper.THINMATHSPACE);
545 AttributesHelper.SIZETRANSLATIONS.put(
546 OperatorDictionary.NAME_MEDIUMMATHSPACE,
547 AttributesHelper.MEDIUMMATHSPACE);
548 AttributesHelper.SIZETRANSLATIONS.put(
549 OperatorDictionary.NAME_THICKMATHSPACE,
550 AttributesHelper.THICKMATHSPACE);
551 AttributesHelper.SIZETRANSLATIONS.put(
552 OperatorDictionary.NAME_VERYTHICKMATHSPACE,
553 AttributesHelper.VERYTHICKMATHSPACE);
554 AttributesHelper.SIZETRANSLATIONS.put(
555 OperatorDictionary.NAME_VERYVERYTHICKMATHSPACE,
556 AttributesHelper.VERYVERYTHICKMATHSPACE);
557 AttributesHelper.SIZETRANSLATIONS.put(OperatorDictionary.NAME_INFINITY,
558 AttributesHelper.INFINITY);
559 AttributesHelper.SIZETRANSLATIONS.put("small", "68%");
560 AttributesHelper.SIZETRANSLATIONS.put("normal", "100%");
561 AttributesHelper.SIZETRANSLATIONS.put("big", "147%");
562
563
564 AttributesHelper.SIZETRANSLATIONS.put("thin", "0.5");
565 AttributesHelper.SIZETRANSLATIONS.put("medium", "1");
566 AttributesHelper.SIZETRANSLATIONS.put("thick", "2");
567
568 AttributesHelper.SIZETRANSLATIONS.put("null", Constants.ZERO);
569
570 AttributesHelper.RELATIVE_UNITS.put("em", AttributesHelper.EM);
571 AttributesHelper.RELATIVE_UNITS.put("ex", AttributesHelper.EX);
572 AttributesHelper.RELATIVE_UNITS.put("% ", AttributesHelper.PERCENT);
573
574 AttributesHelper.ABSOLUTE_UNITS.put("px", 1.0f);
575 AttributesHelper.ABSOLUTE_UNITS.put("in", AttributesHelper.DPI);
576 AttributesHelper.ABSOLUTE_UNITS.put("cm", AttributesHelper.DPI
577 / AttributesHelper.CM_PER_INCH);
578 AttributesHelper.ABSOLUTE_UNITS.put("mm", AttributesHelper.DPI
579 / AttributesHelper.MM_PER_INCH);
580 AttributesHelper.ABSOLUTE_UNITS.put(AttributesHelper.PT, 1.0f);
581 AttributesHelper.ABSOLUTE_UNITS.put("pc", AttributesHelper.PT_PER_PC);
582
583
584 AttributesHelper.COLOR_MAPPINGS.put("aqua", new Color(0, 255, 255));
585 AttributesHelper.COLOR_MAPPINGS.put("black", Color.BLACK);
586 AttributesHelper.COLOR_MAPPINGS.put("blue", Color.BLUE);
587 AttributesHelper.COLOR_MAPPINGS.put("fuchsia", new Color(255, 0, 255));
588 AttributesHelper.COLOR_MAPPINGS.put("gray", Color.GRAY);
589 AttributesHelper.COLOR_MAPPINGS.put("green", Color.GREEN);
590 AttributesHelper.COLOR_MAPPINGS.put("lime", new Color(0, 255, 0));
591 AttributesHelper.COLOR_MAPPINGS.put("maroon", new Color(128, 0, 0));
592 AttributesHelper.COLOR_MAPPINGS.put("navy", new Color(0, 0, 128));
593 AttributesHelper.COLOR_MAPPINGS.put("olive", new Color(128, 128, 0));
594 AttributesHelper.COLOR_MAPPINGS.put("purple", new Color(128, 0, 128));
595 AttributesHelper.COLOR_MAPPINGS.put("red", Color.RED);
596 AttributesHelper.COLOR_MAPPINGS.put("silver", new Color(192, 192, 192));
597 AttributesHelper.COLOR_MAPPINGS.put("teal", new Color(0, 128, 128));
598 AttributesHelper.COLOR_MAPPINGS.put("white", Color.WHITE);
599 AttributesHelper.COLOR_MAPPINGS.put("yellow", Color.YELLOW);
600
601
602 AttributesHelper.COLOR_MAPPINGS.put(AttributesHelper.COLOR_TRANSPARENT,
603 null);
604 AttributesHelper.COLOR_MAPPINGS.put("null", null);
605 AttributesHelper.COLOR_MAPPINGS.put("", null);
606 }
607
608 }