1 14 package org.wings.style; 15 16 import org.wings.SFont; 17 import org.wings.io.Device; 18 19 import java.awt.*; 20 import java.io.*; 21 import java.net.MalformedURLException ; 22 import java.net.URL ; 23 import java.util.*; 24 import java.util.List ; 25 26 public class CSSStyleSheet 27 implements StyleSheet { 28 private static final Map lengthMapping = new HashMap(); 29 30 static { 31 lengthMapping.put("pt", new Float (1f)); 32 lengthMapping.put("px", new Float (1.3f)); 33 lengthMapping.put("mm", new Float (2.83464f)); 34 lengthMapping.put("cm", new Float (28.3464f)); 35 lengthMapping.put("pc", new Float (12f)); 36 lengthMapping.put("in", new Float (72f)); 37 } 38 39 private final Map map; 40 41 public CSSStyleSheet() { 42 map = new HashMap(); 43 } 44 45 public CSSStyleSheet(InputStream in) throws IOException { 46 this(); 47 read(in); 48 } 49 50 public void putStyle(Style style) { 51 map.put(style.getSelector(), style); 52 style.setSheet(this); 53 } 54 55 public Set styles() { 56 return new HashSet(map.values()); 57 } 58 59 62 public void write(Device out) throws IOException { 63 Iterator iterator = map.entrySet().iterator(); 64 while (iterator.hasNext()) { 65 Map.Entry entry = (Map.Entry) iterator.next(); 66 72 ((Style) entry.getValue()).write(out); 73 } 74 out.flush(); 75 } 76 77 public void read(InputStream is) 78 throws IOException { 79 Reader r = new BufferedReader(new InputStreamReader(is)); 80 CssParser parser = new CssParser(); 81 parser.parse(null, r, false, false); 82 } 83 84 public void importStyleSheet(URL url) { 85 try { 86 InputStream is = url.openStream(); 87 Reader r = new BufferedReader(new InputStreamReader(is)); 88 CssParser parser = new CssParser(); 89 parser.parse(url, r, false, true); 90 r.close(); 91 is.close(); 92 } catch (Throwable e) { 93 e.printStackTrace(); 94 } 97 } 98 99 public InputStream getInputStream() throws IOException { 100 return null; 101 }; 102 103 public boolean isFinal() { 104 return false; 105 } 106 107 110 public static SFont getFont(CSSAttributeSet a) { 111 boolean anyFontAttribute = false; 112 int size = getFontSize(a); 113 anyFontAttribute |= (size > 0); 114 115 119 String vAlign = (String ) a.get(CSSProperty.VERTICAL_ALIGN); 120 121 if (vAlign != null) { 122 if ((vAlign.indexOf("sup") >= 0) || 123 (vAlign.indexOf("sub") >= 0)) { 124 size -= 2; 125 } 126 } 127 128 String family = (String ) a.get(CSSProperty.FONT_FAMILY); 129 anyFontAttribute |= (family != null); 130 131 int style = Font.PLAIN; 132 String weight = (String ) a.get(CSSProperty.FONT_WEIGHT); 133 if (weight == null) 134 ; 135 else if (weight.equals("bold")) { 136 style |= Font.BOLD; 137 } else if (weight.equals("normal")) 138 ; 139 else { 140 try { 141 int w = Integer.parseInt(weight); 142 if (w > 400) 143 style |= Font.BOLD; 144 } catch (NumberFormatException nfe) { 145 } 146 } 147 anyFontAttribute |= (weight != null); 148 149 String styleValue = (String ) a.get(CSSProperty.FONT_STYLE); 150 if ((styleValue != null) && (styleValue.toLowerCase().indexOf("italic") >= 0)) style |= Font.ITALIC; 151 anyFontAttribute |= (styleValue != null); 152 return anyFontAttribute ? new SFont(family, style, size) : null; 153 } 154 155 static int sizeMap[] = {8, 10, 12, 14, 18, 24, 36}; 156 157 161 private static int getFontSize(CSSAttributeSet attr) { 162 String value = (String ) attr.get(CSSProperty.FONT_SIZE); 163 if (value == null) 164 return -1; 165 try { 166 if (value.equals("xx-small")) { 167 return 8; 168 } else if (value.equals("x-small")) { 169 return 10; 170 } else if (value.equals("small")) { 171 return 12; 172 } else if (value.equals("medium")) { 173 return 14; 174 } else if (value.equals("large")) { 175 return 18; 176 } else if (value.equals("x-large")) { 177 return 24; 178 } else if (value.equals("xx-large")) { 179 return 36; 180 } else { 181 return new Float (getLength(value)).intValue(); 182 } 183 } catch (NumberFormatException nfe) { 184 return -1; 185 } 186 } 187 188 public static float getLength(String value) { 189 int length = value.length(); 190 if (length >= 2) { 191 String units = value.substring(length - 2, length); 192 Float scale = (Float ) lengthMapping.get(units); 193 194 if (scale != null) { 195 try { 196 return Float.valueOf(value.substring(0, length - 2)).floatValue() * 197 scale.floatValue(); 198 } catch (NumberFormatException nfe) { 199 } 200 } else { 201 try { 203 return Float.valueOf(value).floatValue(); 204 } catch (NumberFormatException nfe) { 205 } 206 } 207 } else if (length > 0) { 208 try { 210 return Float.valueOf(value).floatValue(); 211 } catch (NumberFormatException nfe) { 212 } 213 } 214 return 12.0f; 215 } 216 217 225 public static Color getForeground(CSSAttributeSet a) { 226 return getColor(a, CSSProperty.COLOR); 227 } 228 229 237 public static Color getBackground(CSSAttributeSet a) { 238 return getColor(a, CSSProperty.BACKGROUND_COLOR); 239 } 240 241 static Color getColor(CSSAttributeSet a, CSSProperty cssProperty) { 242 String cv = (String ) a.get(cssProperty); 243 if (cv != null) { 244 return stringToColor(cv); 245 } 246 return null; 247 } 248 249 253 static String colorToHex(Color color) { 254 String colorstr = "#"; 255 256 String str = Integer.toHexString(color.getRed()); 258 if (str.length() > 2) 259 str = str.substring(0, 2); 260 else if (str.length() < 2) 261 colorstr += "0" + str; 262 else 263 colorstr += str; 264 265 str = Integer.toHexString(color.getGreen()); 267 if (str.length() > 2) 268 str = str.substring(0, 2); 269 else if (str.length() < 2) 270 colorstr += "0" + str; 271 else 272 colorstr += str; 273 274 str = Integer.toHexString(color.getBlue()); 276 if (str.length() > 2) 277 str = str.substring(0, 2); 278 else if (str.length() < 2) 279 colorstr += "0" + str; 280 else 281 colorstr += str; 282 283 return colorstr; 284 } 285 286 291 static final Color hexToColor(String value) { 292 String digits; 293 if (value.startsWith("#")) { 294 digits = value.substring(1, Math.min(value.length(), 7)); 295 } else { 296 digits = value; 297 } 298 String hstr = "0x" + digits; 299 Color c; 300 try { 301 c = Color.decode(hstr); 302 } catch (NumberFormatException nfe) { 303 c = null; 304 } 305 return c; 306 } 307 308 312 static Color stringToColor(String str) { 313 Color color = null; 314 315 if (str.length() == 0) 316 color = Color.black; 317 else if (str.startsWith("rgb(")) { 318 color = parseRGB(str); 319 } else if (str.charAt(0) == '#') 320 color = hexToColor(str); 321 else if (str.equalsIgnoreCase("Black")) 322 color = hexToColor("#000000"); 323 else if (str.equalsIgnoreCase("Silver")) 324 color = hexToColor("#C0C0C0"); 325 else if (str.equalsIgnoreCase("Gray")) 326 color = hexToColor("#808080"); 327 else if (str.equalsIgnoreCase("White")) 328 color = hexToColor("#FFFFFF"); 329 else if (str.equalsIgnoreCase("Maroon")) 330 color = hexToColor("#800000"); 331 else if (str.equalsIgnoreCase("Red")) 332 color = hexToColor("#FF0000"); 333 else if (str.equalsIgnoreCase("Purple")) 334 color = hexToColor("#800080"); 335 else if (str.equalsIgnoreCase("Fuchsia")) 336 color = hexToColor("#FF00FF"); 337 else if (str.equalsIgnoreCase("Green")) 338 color = hexToColor("#008000"); 339 else if (str.equalsIgnoreCase("Lime")) 340 color = hexToColor("#00FF00"); 341 else if (str.equalsIgnoreCase("Olive")) 342 color = hexToColor("#808000"); 343 else if (str.equalsIgnoreCase("Yellow")) 344 color = hexToColor("#FFFF00"); 345 else if (str.equalsIgnoreCase("Navy")) 346 color = hexToColor("#000080"); 347 else if (str.equalsIgnoreCase("Blue")) 348 color = hexToColor("#0000FF"); 349 else if (str.equalsIgnoreCase("Teal")) 350 color = hexToColor("#008080"); 351 else if (str.equalsIgnoreCase("Aqua")) 352 color = hexToColor("#00FFFF"); 353 else 354 color = hexToColor(str); return color; 356 } 357 358 364 private static Color parseRGB(String string) { 365 int[] index = new int[1]; 367 368 index[0] = 4; 369 int red = getColorComponent(string, index); 370 int green = getColorComponent(string, index); 371 int blue = getColorComponent(string, index); 372 373 return new Color(red, green, blue); 374 } 375 376 382 private static int getColorComponent(String string, int[] index) { 383 int length = string.length(); 384 char aChar; 385 386 while (index[0] < length && (aChar = string.charAt(index[0])) != '-' && 388 !Character.isDigit(aChar) && aChar != '.') { 389 index[0]++; 390 } 391 392 int start = index[0]; 393 394 if (start < length && string.charAt(index[0]) == '-') { 395 index[0]++; 396 } 397 while (index[0] < length && 398 Character.isDigit(string.charAt(index[0]))) { 399 index[0]++; 400 } 401 if (index[0] < length && string.charAt(index[0]) == '.') { 402 index[0]++; 404 while (index[0] < length && 405 Character.isDigit(string.charAt(index[0]))) { 406 index[0]++; 407 } 408 } 409 if (start != index[0]) { 410 try { 411 float value = Float.parseFloat(string.substring 412 (start, index[0])); 413 414 if (index[0] < length && string.charAt(index[0]) == '%') { 415 index[0]++; 416 value = value * 255f / 100f; 417 } 418 return Math.min(255, Math.max(0, (int) value)); 419 } catch (NumberFormatException nfe) { 420 } 422 } 423 return 0; 424 } 425 426 public static URL getURL(URL base, String cssString) { 427 if (cssString == null) { 428 return null; 429 } 430 if (cssString.startsWith("url(") && 431 cssString.endsWith(")")) { 432 cssString = cssString.substring(4, cssString.length() - 1); 433 } 434 try { 436 URL url = new URL (cssString); 437 if (url != null) { 438 return url; 439 } 440 } catch (MalformedURLException mue) { 441 } 442 if (base != null) { 444 try { 446 URL url = new URL (base, cssString); 447 return url; 448 } catch (MalformedURLException muee) { 449 } 450 } 451 return null; 452 } 453 454 public static CSSAttributeSet getAttributes(SFont font) { 455 CSSAttributeSet attributes = new CSSAttributeSet(); 456 if (font == null) 457 return attributes; 458 attributes.put(CSSProperty.FONT_FAMILY, font.getFace()); 459 460 if ((font.getStyle() & Font.ITALIC) > 0) 461 attributes.put(CSSProperty.FONT_STYLE, "italic"); 462 463 if ((font.getStyle() & Font.BOLD) > 0) 464 attributes.put(CSSProperty.FONT_WEIGHT, "bold"); 465 466 attributes.put(CSSProperty.FONT_SIZE, font.getSize() + "pt"); 467 return attributes; 468 } 469 470 public static CSSAttributeSet getAttributes(Color color, CSSProperty cssProperty) { 471 CSSAttributeSet attributes = new CSSAttributeSet(); 472 if (color != null) 473 attributes.put(cssProperty, colorToHex(color)); 474 return attributes; 475 } 476 477 public static String getAttribute(Color color) { 478 if (color != null) 479 return colorToHex(color); 480 return null; 481 } 482 483 class CssParser 484 implements CSSParser.CSSParserCallback { 485 488 public CSSAttributeSet parseDeclaration(String string) { 489 try { 490 return parseDeclaration(new StringReader(string)); 491 } catch (IOException ioe) { 492 } 493 return null; 494 } 495 496 499 public CSSAttributeSet parseDeclaration(Reader r) throws IOException { 500 parse(base, r, true, false); 501 return new CSSAttributeSet(declaration); 502 } 503 504 507 public void parse(URL base, Reader r, boolean parseDeclaration, boolean isLink) 508 throws IOException { 509 this.base = base; 510 declaration.clear(); 513 selectorTokens.clear(); 514 selectors.clear(); 515 propertyName = null; 516 parser.parse(r, this, parseDeclaration); 517 } 518 519 523 529 public void handleImport(String importString) { 530 URL url = CSSStyleSheet.getURL(base, importString); 531 if (url != null) { 532 importStyleSheet(url); 533 } 534 } 535 536 539 public void handleSelector(String selector) { 540 selector = selector.toLowerCase(); 541 542 int length = selector.length(); 543 544 if (selector.endsWith(",")) { 545 if (length > 1) { 546 selector = selector.substring(0, length - 1); 547 selectorTokens.add(selector); 548 } 549 addSelector(); 550 } else if (length > 0) { 551 selectorTokens.add(selector); 552 } 553 } 554 555 558 public void startRule() { 559 if (selectorTokens.size() > 0) { 560 addSelector(); 561 } 562 propertyName = null; 563 } 564 565 568 public void handleProperty(String property) { 569 propertyName = property; 570 } 571 572 575 public void handleValue(String value) { 576 if (propertyName != null) { 577 declaration.put(new CSSProperty(propertyName), value); 578 } 579 propertyName = null; 580 } 581 582 585 public void endRule() { 586 int n = selectors.size(); 587 for (int i = 0; i < n; i++) { 588 String [] selector = (String []) selectors.get(i); 589 for (int j = selector.length - 1; j >= 0; --j) { 590 CSSStyleSheet.this.putStyle(new CSSStyle(new CSSSelector(selector[j]), declaration)); 591 } 592 } 593 declaration.clear(); 594 selectors.clear(); 595 } 596 597 private void addSelector() { 598 String [] selector = new String [selectorTokens.size()]; 599 selector = (String []) selectorTokens.toArray(selector); 600 selectors.add(selector); 601 selectorTokens.clear(); 602 } 603 604 List selectors = new LinkedList(); 605 List selectorTokens = new LinkedList(); 606 609 String propertyName; 610 CSSAttributeSet declaration = new CSSAttributeSet(); 611 613 615 619 URL base; 620 CSSParser parser = new CSSParser(); 621 } 622 } 623 624 625 | Popular Tags |