1 17 18 19 20 package org.apache.fop.util; 21 22 import java.awt.Color ; 23 import java.awt.color.ColorSpace ; 24 import java.util.Collections ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.StringTokenizer ; 29 30 import org.apache.commons.logging.Log; 31 import org.apache.commons.logging.LogFactory; 32 import org.apache.fop.apps.FOUserAgent; 33 import org.apache.fop.fo.expr.PropertyException; 34 35 41 public final class ColorUtil { 42 43 50 private static Map colorMap = null; 51 52 53 protected static Log log = LogFactory.getLog(ColorUtil.class); 54 55 static { 56 initializeColorMap(); 57 } 58 59 62 private ColorUtil() { 63 } 64 65 91 public static Color parseColorString(FOUserAgent foUserAgent, String value) 92 throws PropertyException { 93 if (value == null) { 94 return null; 95 } 96 97 Color parsedColor = (Color ) colorMap.get(value.toLowerCase()); 98 99 if (parsedColor == null) { 100 if (value.startsWith("#")) { 101 parsedColor = parseWithHash(value); 102 } else if (value.startsWith("rgb(")) { 103 parsedColor = parseAsRGB(value); 104 } else if (value.startsWith("url(")) { 105 throw new PropertyException( 106 "Colors starting with url( are not yet supported!"); 107 } else if (value.startsWith("java.awt.Color")) { 108 parsedColor = parseAsJavaAWTColor(value); 109 } else if (value.startsWith("system-color(")) { 110 parsedColor = parseAsSystemColor(value); 111 } else if (value.startsWith("fop-rgb-icc")) { 112 parsedColor = parseAsFopRgbIcc(foUserAgent, value); 113 } else if (value.startsWith("cmyk")) { 114 parsedColor = parseAsCMYK(value); 115 } 116 117 if (parsedColor == null) { 118 throw new PropertyException("Unknown Color: " + value); 119 } 120 121 colorMap.put(value, parsedColor); 122 } 123 124 return parsedColor; 128 } 129 130 139 private static Color parseAsSystemColor(String value) 140 throws PropertyException { 141 int poss = value.indexOf("("); 142 int pose = value.indexOf(")"); 143 if (poss != -1 && pose != -1) { 144 value = value.substring(poss + 1, pose); 145 } else { 146 throw new PropertyException("Unknown color format: " + value 147 + ". Must be system-color(x)"); 148 } 149 return (Color ) colorMap.get(value); 150 } 151 152 162 private static Color parseAsJavaAWTColor(String value) 163 throws PropertyException { 164 float red = 0.0f, green = 0.0f, blue = 0.0f; 165 int poss = value.indexOf("["); 166 int pose = value.indexOf("]"); 167 try { 168 if (poss != -1 && pose != -1) { 169 value = value.substring(poss + 1, pose); 170 StringTokenizer st = new StringTokenizer (value, ","); 171 if (st.hasMoreTokens()) { 172 String str = st.nextToken().trim(); 173 red = Float.parseFloat(str.substring(2)) / 255f; 174 } 175 if (st.hasMoreTokens()) { 176 String str = st.nextToken().trim(); 177 green = Float.parseFloat(str.substring(2)) / 255f; 178 } 179 if (st.hasMoreTokens()) { 180 String str = st.nextToken().trim(); 181 blue = Float.parseFloat(str.substring(2)) / 255f; 182 } else { 183 throw new NumberFormatException (); 184 } 185 if ((red < 0.0 || red > 1.0) || (green < 0.0 || green > 1.0) 186 || (blue < 0.0 || blue > 1.0)) { 187 throw new PropertyException("Color values out of range"); 188 } 189 } else { 190 throw new NullPointerException (); 191 } 192 } catch (Exception e) { 193 throw new PropertyException("Unknown color format: " + value); 194 } 195 return new Color (red, green, blue); 196 } 197 198 207 private static Color parseAsRGB(String value) throws PropertyException { 208 Color parsedColor; 209 int poss = value.indexOf("("); 210 int pose = value.indexOf(")"); 211 if (poss != -1 && pose != -1) { 212 value = value.substring(poss + 1, pose); 213 StringTokenizer st = new StringTokenizer (value, ","); 214 try { 215 float red = 0.0f, green = 0.0f, blue = 0.0f; 216 if (st.hasMoreTokens()) { 217 String str = st.nextToken().trim(); 218 if (str.endsWith("%")) { 219 red = Float.parseFloat(str.substring(0, 220 str.length() - 1)) / 100.0f; 221 } else { 222 red = Float.parseFloat(str) / 255f; 223 } 224 } 225 if (st.hasMoreTokens()) { 226 String str = st.nextToken().trim(); 227 if (str.endsWith("%")) { 228 green = Float.parseFloat(str.substring(0, 229 str.length() - 1)) / 100.0f; 230 } else { 231 green = Float.parseFloat(str) / 255f; 232 } 233 } 234 if (st.hasMoreTokens()) { 235 String str = st.nextToken().trim(); 236 if (str.endsWith("%")) { 237 blue = Float.parseFloat(str.substring(0, 238 str.length() - 1)) / 100.0f; 239 } else { 240 blue = Float.parseFloat(str) / 255f; 241 } 242 } 243 if ((red < 0.0 || red > 1.0) || (green < 0.0 || green > 1.0) 244 || (blue < 0.0 || blue > 1.0)) { 245 throw new PropertyException("Color values out of range"); 246 } 247 parsedColor = new Color (red, green, blue); 248 } catch (Exception e) { 249 throw new PropertyException( 250 "Arguments to rgb() must be [0..255] or [0%..100%]"); 251 } 252 } else { 253 throw new PropertyException("Unknown color format: " + value 254 + ". Must be rgb(r,g,b)"); 255 } 256 return parsedColor; 257 } 258 259 268 private static Color parseWithHash(String value) throws PropertyException { 269 Color parsedColor = null; 270 try { 271 int len = value.length(); 272 if ((len >= 4) && (len <= 5)) { 273 float red = Integer.parseInt(value.substring(1, 2), 16) / 15f; 275 float green = Integer.parseInt(value.substring(2, 3), 16) / 15f; 276 float blue = Integer.parseInt(value.substring(3, 4), 16) / 15f; 277 float alpha = 1.0f; 278 if (len == 5) { 279 alpha = Integer.parseInt(value.substring(4), 16) / 15f; 280 } 281 parsedColor = new Color (red, green, blue, alpha); 282 } else if ((len == 7) || (len == 9)) { 283 int red = Integer.parseInt(value.substring(1, 3), 16); 284 int green = Integer.parseInt(value.substring(3, 5), 16); 285 int blue = Integer.parseInt(value.substring(5, 7), 16); 286 int alpha = 255; 287 if (len == 9) { 288 alpha = Integer.parseInt(value.substring(7), 16); 289 } 290 parsedColor = new Color (red, green, blue, alpha); 291 } else { 292 throw new NumberFormatException (); 293 } 294 } catch (NumberFormatException e) { 295 throw new PropertyException("Unknown color format: " + value 296 + ". Must be #RGB. #RGBA, #RRGGBB, or #RRGGBBAA"); 297 } 298 return parsedColor; 299 } 300 301 308 private static Color parseAsFopRgbIcc(FOUserAgent foUserAgent, String value) 309 throws PropertyException { 310 Color parsedColor; 311 int poss = value.indexOf("("); 312 int pose = value.indexOf(")"); 313 if (poss != -1 && pose != -1) { 314 value = value.substring(poss + 1, pose); 315 StringTokenizer st = new StringTokenizer (value, ","); 316 try { 317 float red = 0.0f, green = 0.0f, blue = 0.0f; 318 if (st.hasMoreTokens()) { 319 String str = st.nextToken().trim(); 320 red = Float.parseFloat(str); 321 } 322 if (st.hasMoreTokens()) { 323 String str = st.nextToken().trim(); 324 green = Float.parseFloat(str); 325 } 326 if (st.hasMoreTokens()) { 327 String str = st.nextToken().trim(); 328 blue = Float.parseFloat(str); 329 } 330 331 if ((red < 0.0 || red > 1.0) 332 || (green < 0.0 || green > 1.0) 333 || (blue < 0.0 || blue > 1.0)) { 334 throw new PropertyException("Color values out of range"); 335 } 336 337 String iccProfileName = null; 338 if (st.hasMoreTokens()) { 339 iccProfileName = st.nextToken().trim(); 340 } 341 if (iccProfileName == null || iccProfileName.length() == 0) { 342 throw new PropertyException("ICC profile name missing"); 343 } 344 345 String iccProfileSrc = null; 346 if (st.hasMoreTokens()) { 347 iccProfileSrc = st.nextToken().trim(); 348 iccProfileSrc = iccProfileSrc.substring(1, iccProfileSrc.length() - 1); 350 } 351 if (iccProfileSrc == null || iccProfileSrc.length() == 0) { 352 throw new PropertyException("ICC profile source missing"); 353 } 354 355 List iccArgList = new LinkedList (); 356 while (st.hasMoreTokens()) { 357 String str = st.nextToken().trim(); 358 iccArgList.add(new Float (str)); 359 } 360 361 float[] iccComponents = new float[iccArgList.size()]; 362 for (int ix = 0; ix < iccArgList.size(); ix++) { 363 iccComponents[ix] = ((Float )iccArgList.get(ix)).floatValue(); 364 } 365 366 ColorSpace colorSpace = (foUserAgent != null 367 ? foUserAgent.getFactory().getColorSpace( 368 foUserAgent.getBaseURL(), iccProfileSrc) : null); 369 if (colorSpace != null) { 370 parsedColor = ColorExt.createFromFoRgbIcc(red, green, blue, 373 iccProfileName, iccProfileSrc, colorSpace, iccComponents); 374 } else { 375 log.warn("Color profile '" + iccProfileSrc 377 + "' not found. Using rgb replacement values."); 378 parsedColor = new Color (red, green, blue); 379 } 380 } catch (Exception e) { 381 throw new PropertyException( 382 "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); 383 } 384 } else { 385 throw new PropertyException("Unknown color format: " + value 386 + ". Must be fop-rgb-icc(r,g,b,NCNAME,\"src\",....)"); 387 } 388 return parsedColor; 389 } 390 391 400 private static Color parseAsCMYK(String value) throws PropertyException { 401 Color parsedColor; 402 int poss = value.indexOf("("); 403 int pose = value.indexOf(")"); 404 if (poss != -1 && pose != -1) { 405 value = value.substring(poss + 1, pose); 406 StringTokenizer st = new StringTokenizer (value, ","); 407 try { 408 float cyan = 0.0f, magenta = 0.0f, yellow = 0.0f, black = 0.0f; 409 if (st.hasMoreTokens()) { 410 String str = st.nextToken().trim(); 411 if (str.endsWith("%")) { 412 cyan = Float.parseFloat(str.substring(0, 413 str.length() - 1)) / 100.0f; 414 } else { 415 cyan = Float.parseFloat(str); 416 } 417 } 418 if (st.hasMoreTokens()) { 419 String str = st.nextToken().trim(); 420 if (str.endsWith("%")) { 421 magenta = Float.parseFloat(str.substring(0, 422 str.length() - 1)) / 100.0f; 423 } else { 424 magenta = Float.parseFloat(str); 425 } 426 } 427 if (st.hasMoreTokens()) { 428 String str = st.nextToken().trim(); 429 if (str.endsWith("%")) { 430 yellow = Float.parseFloat(str.substring(0, 431 str.length() - 1)) / 100.0f; 432 } else { 433 yellow = Float.parseFloat(str); 434 } 435 } 436 if (st.hasMoreTokens()) { 437 String str = st.nextToken().trim(); 438 if (str.endsWith("%")) { 439 black = Float.parseFloat(str.substring(0, 440 str.length() - 1)) / 100.0f; 441 } else { 442 black = Float.parseFloat(str); 443 } 444 } 445 if ((cyan < 0.0 || cyan > 1.0) 446 || (magenta < 0.0 || magenta > 1.0) 447 || (yellow < 0.0 || yellow > 1.0) 448 || (black < 0.0 || black > 1.0)) { 449 throw new PropertyException("Color values out of range"); 450 } 451 float[] cmyk = new float[] {cyan, magenta, yellow, black}; 452 CMYKColorSpace cmykCs = CMYKColorSpace.getInstance(); 453 float[] rgb = cmykCs.toRGB(cmyk); 454 parsedColor = ColorExt.createFromFoRgbIcc(rgb[0], rgb[1], rgb[2], 455 null, "#CMYK", cmykCs, cmyk); 456 457 458 } catch (Exception e) { 459 throw new PropertyException( 460 "Arguments to cmyk() must be in the range [0%-100%] or [0.0-1.0]"); 461 } 462 } else { 463 throw new PropertyException("Unknown color format: " + value 464 + ". Must be cmyk(c,m,y,k)"); 465 } 466 return parsedColor; 467 } 468 469 479 public static String colorToString(Color color) { 480 ColorSpace cs = color.getColorSpace(); 481 if (cs != null && cs.getType() == ColorSpace.TYPE_CMYK) { 482 StringBuffer sbuf = new StringBuffer (24); 483 float[] cmyk = color.getColorComponents(null); 484 sbuf.append("cmyk(" + cmyk[0] + "," + cmyk[1] + "," + cmyk[2] + "," + cmyk[3] + ")"); 485 return sbuf.toString(); 486 } else if (color instanceof ColorExt) { 487 return ((ColorExt)color).toFunctionCall(); 488 } else { 489 StringBuffer sbuf = new StringBuffer (); 490 sbuf.append('#'); 491 String s = Integer.toHexString(color.getRed()); 492 if (s.length() == 1) { 493 sbuf.append('0'); 494 } 495 sbuf.append(s); 496 s = Integer.toHexString(color.getGreen()); 497 if (s.length() == 1) { 498 sbuf.append('0'); 499 } 500 sbuf.append(s); 501 s = Integer.toHexString(color.getBlue()); 502 if (s.length() == 1) { 503 sbuf.append('0'); 504 } 505 sbuf.append(s); 506 if (color.getAlpha() != 255) { 507 s = Integer.toHexString(color.getAlpha()); 508 if (s.length() == 1) { 509 sbuf.append('0'); 510 } 511 sbuf.append(s); 512 } 513 return sbuf.toString(); 514 } 515 } 516 517 520 private static void initializeColorMap() { 521 colorMap = Collections.synchronizedMap(new java.util.HashMap ()); 522 523 colorMap.put("aliceblue", new Color (240, 248, 255)); 524 colorMap.put("antiquewhite", new Color (250, 235, 215)); 525 colorMap.put("aqua", new Color (0, 255, 255)); 526 colorMap.put("aquamarine", new Color (127, 255, 212)); 527 colorMap.put("azure", new Color (240, 255, 255)); 528 colorMap.put("beige", new Color (245, 245, 220)); 529 colorMap.put("bisque", new Color (255, 228, 196)); 530 colorMap.put("black", new Color (0, 0, 0)); 531 colorMap.put("blanchedalmond", new Color (255, 235, 205)); 532 colorMap.put("blue", new Color (0, 0, 255)); 533 colorMap.put("blueviolet", new Color (138, 43, 226)); 534 colorMap.put("brown", new Color (165, 42, 42)); 535 colorMap.put("burlywood", new Color (222, 184, 135)); 536 colorMap.put("cadetblue", new Color (95, 158, 160)); 537 colorMap.put("chartreuse", new Color (127, 255, 0)); 538 colorMap.put("chocolate", new Color (210, 105, 30)); 539 colorMap.put("coral", new Color (255, 127, 80)); 540 colorMap.put("cornflowerblue", new Color (100, 149, 237)); 541 colorMap.put("cornsilk", new Color (255, 248, 220)); 542 colorMap.put("crimson", new Color (220, 20, 60)); 543 colorMap.put("cyan", new Color (0, 255, 255)); 544 colorMap.put("darkblue", new Color (0, 0, 139)); 545 colorMap.put("darkcyan", new Color (0, 139, 139)); 546 colorMap.put("darkgoldenrod", new Color (184, 134, 11)); 547 colorMap.put("darkgray", new Color (169, 169, 169)); 548 colorMap.put("darkgreen", new Color (0, 100, 0)); 549 colorMap.put("darkgrey", new Color (169, 169, 169)); 550 colorMap.put("darkkhaki", new Color (189, 183, 107)); 551 colorMap.put("darkmagenta", new Color (139, 0, 139)); 552 colorMap.put("darkolivegreen", new Color (85, 107, 47)); 553 colorMap.put("darkorange", new Color (255, 140, 0)); 554 colorMap.put("darkorchid", new Color (153, 50, 204)); 555 colorMap.put("darkred", new Color (139, 0, 0)); 556 colorMap.put("darksalmon", new Color (233, 150, 122)); 557 colorMap.put("darkseagreen", new Color (143, 188, 143)); 558 colorMap.put("darkslateblue", new Color (72, 61, 139)); 559 colorMap.put("darkslategray", new Color (47, 79, 79)); 560 colorMap.put("darkslategrey", new Color (47, 79, 79)); 561 colorMap.put("darkturquoise", new Color (0, 206, 209)); 562 colorMap.put("darkviolet", new Color (148, 0, 211)); 563 colorMap.put("deeppink", new Color (255, 20, 147)); 564 colorMap.put("deepskyblue", new Color (0, 191, 255)); 565 colorMap.put("dimgray", new Color (105, 105, 105)); 566 colorMap.put("dimgrey", new Color (105, 105, 105)); 567 colorMap.put("dodgerblue", new Color (30, 144, 255)); 568 colorMap.put("firebrick", new Color (178, 34, 34)); 569 colorMap.put("floralwhite", new Color (255, 250, 240)); 570 colorMap.put("forestgreen", new Color (34, 139, 34)); 571 colorMap.put("fuchsia", new Color (255, 0, 255)); 572 colorMap.put("gainsboro", new Color (220, 220, 220)); 573 colorMap.put("ghostwhite", new Color (248, 248, 255)); 574 colorMap.put("gold", new Color (255, 215, 0)); 575 colorMap.put("goldenrod", new Color (218, 165, 32)); 576 colorMap.put("gray", new Color (128, 128, 128)); 577 colorMap.put("green", new Color (0, 128, 0)); 578 colorMap.put("greenyellow", new Color (173, 255, 47)); 579 colorMap.put("grey", new Color (128, 128, 128)); 580 colorMap.put("honeydew", new Color (240, 255, 240)); 581 colorMap.put("hotpink", new Color (255, 105, 180)); 582 colorMap.put("indianred", new Color (205, 92, 92)); 583 colorMap.put("indigo", new Color (75, 0, 130)); 584 colorMap.put("ivory", new Color (255, 255, 240)); 585 colorMap.put("khaki", new Color (240, 230, 140)); 586 colorMap.put("lavender", new Color (230, 230, 250)); 587 colorMap.put("lavenderblush", new Color (255, 240, 245)); 588 colorMap.put("lawngreen", new Color (124, 252, 0)); 589 colorMap.put("lemonchiffon", new Color (255, 250, 205)); 590 colorMap.put("lightblue", new Color (173, 216, 230)); 591 colorMap.put("lightcoral", new Color (240, 128, 128)); 592 colorMap.put("lightcyan", new Color (224, 255, 255)); 593 colorMap.put("lightgoldenrodyellow", new Color (250, 250, 210)); 594 colorMap.put("lightgray", new Color (211, 211, 211)); 595 colorMap.put("lightgreen", new Color (144, 238, 144)); 596 colorMap.put("lightgrey", new Color (211, 211, 211)); 597 colorMap.put("lightpink", new Color (255, 182, 193)); 598 colorMap.put("lightsalmon", new Color (255, 160, 122)); 599 colorMap.put("lightseagreen", new Color (32, 178, 170)); 600 colorMap.put("lightskyblue", new Color (135, 206, 250)); 601 colorMap.put("lightslategray", new Color (119, 136, 153)); 602 colorMap.put("lightslategrey", new Color (119, 136, 153)); 603 colorMap.put("lightsteelblue", new Color (176, 196, 222)); 604 colorMap.put("lightyellow", new Color (255, 255, 224)); 605 colorMap.put("lime", new Color (0, 255, 0)); 606 colorMap.put("limegreen", new Color (50, 205, 50)); 607 colorMap.put("linen", new Color (250, 240, 230)); 608 colorMap.put("magenta", new Color (255, 0, 255)); 609 colorMap.put("maroon", new Color (128, 0, 0)); 610 colorMap.put("mediumaquamarine", new Color (102, 205, 170)); 611 colorMap.put("mediumblue", new Color (0, 0, 205)); 612 colorMap.put("mediumorchid", new Color (186, 85, 211)); 613 colorMap.put("mediumpurple", new Color (147, 112, 219)); 614 colorMap.put("mediumseagreen", new Color (60, 179, 113)); 615 colorMap.put("mediumslateblue", new Color (123, 104, 238)); 616 colorMap.put("mediumspringgreen", new Color (0, 250, 154)); 617 colorMap.put("mediumturquoise", new Color (72, 209, 204)); 618 colorMap.put("mediumvioletred", new Color (199, 21, 133)); 619 colorMap.put("midnightblue", new Color (25, 25, 112)); 620 colorMap.put("mintcream", new Color (245, 255, 250)); 621 colorMap.put("mistyrose", new Color (255, 228, 225)); 622 colorMap.put("moccasin", new Color (255, 228, 181)); 623 colorMap.put("navajowhite", new Color (255, 222, 173)); 624 colorMap.put("navy", new Color (0, 0, 128)); 625 colorMap.put("oldlace", new Color (253, 245, 230)); 626 colorMap.put("olive", new Color (128, 128, 0)); 627 colorMap.put("olivedrab", new Color (107, 142, 35)); 628 colorMap.put("orange", new Color (255, 165, 0)); 629 colorMap.put("orangered", new Color (255, 69, 0)); 630 colorMap.put("orchid", new Color (218, 112, 214)); 631 colorMap.put("palegoldenrod", new Color (238, 232, 170)); 632 colorMap.put("palegreen", new Color (152, 251, 152)); 633 colorMap.put("paleturquoise", new Color (175, 238, 238)); 634 colorMap.put("palevioletred", new Color (219, 112, 147)); 635 colorMap.put("papayawhip", new Color (255, 239, 213)); 636 colorMap.put("peachpuff", new Color (255, 218, 185)); 637 colorMap.put("peru", new Color (205, 133, 63)); 638 colorMap.put("pink", new Color (255, 192, 203)); 639 colorMap.put("plum ", new Color (221, 160, 221)); 640 colorMap.put("plum", new Color (221, 160, 221)); 641 colorMap.put("powderblue", new Color (176, 224, 230)); 642 colorMap.put("purple", new Color (128, 0, 128)); 643 colorMap.put("red", new Color (255, 0, 0)); 644 colorMap.put("rosybrown", new Color (188, 143, 143)); 645 colorMap.put("royalblue", new Color (65, 105, 225)); 646 colorMap.put("saddlebrown", new Color (139, 69, 19)); 647 colorMap.put("salmon", new Color (250, 128, 114)); 648 colorMap.put("sandybrown", new Color (244, 164, 96)); 649 colorMap.put("seagreen", new Color (46, 139, 87)); 650 colorMap.put("seashell", new Color (255, 245, 238)); 651 colorMap.put("sienna", new Color (160, 82, 45)); 652 colorMap.put("silver", new Color (192, 192, 192)); 653 colorMap.put("skyblue", new Color (135, 206, 235)); 654 colorMap.put("slateblue", new Color (106, 90, 205)); 655 colorMap.put("slategray", new Color (112, 128, 144)); 656 colorMap.put("slategrey", new Color (112, 128, 144)); 657 colorMap.put("snow", new Color (255, 250, 250)); 658 colorMap.put("springgreen", new Color (0, 255, 127)); 659 colorMap.put("steelblue", new Color (70, 130, 180)); 660 colorMap.put("tan", new Color (210, 180, 140)); 661 colorMap.put("teal", new Color (0, 128, 128)); 662 colorMap.put("thistle", new Color (216, 191, 216)); 663 colorMap.put("tomato", new Color (255, 99, 71)); 664 colorMap.put("turquoise", new Color (64, 224, 208)); 665 colorMap.put("violet", new Color (238, 130, 238)); 666 colorMap.put("wheat", new Color (245, 222, 179)); 667 colorMap.put("white", new Color (255, 255, 255)); 668 colorMap.put("whitesmoke", new Color (245, 245, 245)); 669 colorMap.put("yellow", new Color (255, 255, 0)); 670 colorMap.put("yellowgreen", new Color (154, 205, 50)); 671 672 colorMap.put("transparent", new Color (0, 0, 0, 0)); 673 } 674 675 } 676 | Popular Tags |