1 7 package javax.swing.text.html; 8 9 import com.sun.java.swing.SwingUtilities2; 10 import java.util.*; 11 import java.awt.*; 12 import java.io.*; 13 import java.net.*; 14 import javax.swing.Icon ; 15 import javax.swing.ImageIcon ; 16 import javax.swing.border.*; 17 import javax.swing.event.ChangeListener ; 18 import javax.swing.text.*; 19 20 112 public class StyleSheet extends StyleContext { 113 144 147 public StyleSheet() { 148 super(); 149 selectorMapping = new SelectorMapping(0); 150 resolvedStyles = new Hashtable(); 151 if (css == null) { 152 css = new CSS (); 153 } 154 } 155 156 171 public Style getRule(HTML.Tag t, Element e) { 172 SearchBuffer sb = SearchBuffer.obtainSearchBuffer(); 173 174 try { 175 Vector searchContext = sb.getVector(); 177 178 for (Element p = e; p != null; p = p.getParentElement()) { 179 searchContext.addElement(p); 180 } 181 182 int n = searchContext.size(); 184 StringBuffer cacheLookup = sb.getStringBuffer(); 185 AttributeSet attr; 186 String eName; 187 Object name; 188 189 for (int counter = n - 1; counter >= 1; counter--) { 191 e = (Element)searchContext.elementAt(counter); 192 attr = e.getAttributes(); 193 name = attr.getAttribute(StyleConstants.NameAttribute); 194 eName = name.toString(); 195 cacheLookup.append(eName); 196 if (attr != null) { 197 if (attr.isDefined(HTML.Attribute.ID)) { 198 cacheLookup.append('#'); 199 cacheLookup.append(attr.getAttribute 200 (HTML.Attribute.ID)); 201 } 202 else if (attr.isDefined(HTML.Attribute.CLASS)) { 203 cacheLookup.append('.'); 204 cacheLookup.append(attr.getAttribute 205 (HTML.Attribute.CLASS)); 206 } 207 } 208 cacheLookup.append(' '); 209 } 210 cacheLookup.append(t.toString()); 211 e = (Element)searchContext.elementAt(0); 212 attr = e.getAttributes(); 213 if (e.isLeaf()) { 214 Object testAttr = attr.getAttribute(t); 216 if (testAttr instanceof AttributeSet) { 217 attr = (AttributeSet)testAttr; 218 } 219 else { 220 attr = null; 221 } 222 } 223 if (attr != null) { 224 if (attr.isDefined(HTML.Attribute.ID)) { 225 cacheLookup.append('#'); 226 cacheLookup.append(attr.getAttribute(HTML.Attribute.ID)); 227 } 228 else if (attr.isDefined(HTML.Attribute.CLASS)) { 229 cacheLookup.append('.'); 230 cacheLookup.append(attr.getAttribute 231 (HTML.Attribute.CLASS)); 232 } 233 } 234 235 Style style = getResolvedStyle(cacheLookup.toString(), 236 searchContext, t); 237 return style; 238 } 239 finally { 240 SearchBuffer.releaseSearchBuffer(sb); 241 } 242 } 243 244 255 public Style getRule(String selector) { 256 selector = cleanSelectorString(selector); 257 if (selector != null) { 258 Style style = getResolvedStyle(selector); 259 return style; 260 } 261 return null; 262 } 263 264 269 public void addRule(String rule) { 270 if (rule != null) { 271 final String baseUnitsDisable = "BASE_SIZE_DISABLE"; 274 final String baseUnits = "BASE_SIZE "; 275 final String w3cLengthUnitsEnable = "W3C_LENGTH_UNITS_ENABLE"; 276 final String w3cLengthUnitsDisable = "W3C_LENGTH_UNITS_DISABLE"; 277 if (rule == baseUnitsDisable) { 278 sizeMap = sizeMapDefault; 279 } else if (rule.startsWith(baseUnits)) { 280 rebaseSizeMap(Integer. 281 parseInt(rule.substring(baseUnits.length()))); 282 } else if (rule == w3cLengthUnitsEnable) { 283 w3cLengthUnits = true; 284 } else if (rule == w3cLengthUnitsDisable) { 285 w3cLengthUnits = false; 286 } else { 287 CssParser parser = new CssParser(); 288 try { 289 parser.parse(getBase(), new StringReader(rule), false, false); 290 } catch (IOException ioe) { } 291 } 292 } 293 } 294 295 300 public AttributeSet getDeclaration(String decl) { 301 if (decl == null) { 302 return SimpleAttributeSet.EMPTY; 303 } 304 CssParser parser = new CssParser(); 305 return parser.parseDeclaration(decl); 306 } 307 308 319 public void loadRules(Reader in, URL ref) throws IOException { 320 CssParser parser = new CssParser(); 321 parser.parse(ref, in, false, false); 322 } 323 324 329 public AttributeSet getViewAttributes(View v) { 330 return new ViewAttributeSet(v); 331 } 332 333 338 public void removeStyle(String nm) { 339 Style aStyle = getStyle(nm); 340 341 if (aStyle != null) { 342 String selector = cleanSelectorString(nm); 343 String [] selectors = getSimpleSelectors(selector); 344 synchronized(this) { 345 SelectorMapping mapping = getRootSelectorMapping(); 346 for (int i = selectors.length - 1; i >= 0; i--) { 347 mapping = mapping.getChildSelectorMapping(selectors[i], 348 true); 349 } 350 Style rule = mapping.getStyle(); 351 if (rule != null) { 352 mapping.setStyle(null); 353 if (resolvedStyles.size() > 0) { 354 Enumeration values = resolvedStyles.elements(); 355 while (values.hasMoreElements()) { 356 ResolvedStyle style = (ResolvedStyle)values. 357 nextElement(); 358 style.removeStyle(rule); 359 } 360 } 361 } 362 } 363 } 364 super.removeStyle(nm); 365 } 366 367 375 public void addStyleSheet(StyleSheet ss) { 376 synchronized(this) { 377 if (linkedStyleSheets == null) { 378 linkedStyleSheets = new Vector(); 379 } 380 if (!linkedStyleSheets.contains(ss)) { 381 int index = 0; 382 if (ss instanceof javax.swing.plaf.UIResource 383 && linkedStyleSheets.size() > 1) { 384 index = linkedStyleSheets.size() - 1; 385 } 386 linkedStyleSheets.insertElementAt(ss, index); 387 linkStyleSheetAt(ss, index); 388 } 389 } 390 } 391 392 397 public void removeStyleSheet(StyleSheet ss) { 398 synchronized(this) { 399 if (linkedStyleSheets != null) { 400 int index = linkedStyleSheets.indexOf(ss); 401 if (index != -1) { 402 linkedStyleSheets.removeElementAt(index); 403 unlinkStyleSheet(ss, index); 404 if (index == 0 && linkedStyleSheets.size() == 0) { 405 linkedStyleSheets = null; 406 } 407 } 408 } 409 } 410 } 411 412 416 422 public StyleSheet [] getStyleSheets() { 423 StyleSheet [] retValue; 424 425 synchronized(this) { 426 if (linkedStyleSheets != null) { 427 retValue = new StyleSheet [linkedStyleSheets.size()]; 428 linkedStyleSheets.copyInto(retValue); 429 } 430 else { 431 retValue = null; 432 } 433 } 434 return retValue; 435 } 436 437 445 public void importStyleSheet(URL url) { 446 try { 447 InputStream is; 448 449 is = url.openStream(); 450 Reader r = new BufferedReader(new InputStreamReader(is)); 451 CssParser parser = new CssParser(); 452 parser.parse(url, r, false, true); 453 r.close(); 454 is.close(); 455 } catch (Throwable e) { 456 } 459 } 460 461 467 public void setBase(URL base) { 468 this.base = base; 469 } 470 471 476 public URL getBase() { 477 return base; 478 } 479 480 485 public void addCSSAttribute(MutableAttributeSet attr, CSS.Attribute key, 486 String value) { 487 css.addInternalCSSValue(attr, key, value); 488 } 489 490 495 public boolean addCSSAttributeFromHTML(MutableAttributeSet attr, 496 CSS.Attribute key, String value) { 497 Object iValue = css.getCssValue(key, value); 498 if (iValue != null) { 499 attr.addAttribute(key, iValue); 500 return true; 501 } 502 return false; 503 } 504 505 507 513 public AttributeSet translateHTMLToCSS(AttributeSet htmlAttrSet) { 514 AttributeSet cssAttrSet = css.translateHTMLToCSS(htmlAttrSet); 515 516 MutableAttributeSet cssStyleSet = addStyle(null, null); 517 cssStyleSet.addAttributes(cssAttrSet); 518 519 return cssStyleSet; 520 } 521 522 536 public AttributeSet addAttribute(AttributeSet old, Object key, 537 Object value) { 538 if (css == null) { 539 css = new CSS (); 542 } 543 if (key instanceof StyleConstants) { 544 HTML.Tag tag = HTML.getTagForStyleConstantsKey( 545 (StyleConstants)key); 546 547 if (tag != null && old.isDefined(tag)) { 548 old = removeAttribute(old, tag); 549 } 550 551 Object cssValue = css.styleConstantsValueToCSSValue 552 ((StyleConstants)key, value); 553 if (cssValue != null) { 554 Object cssKey = css.styleConstantsKeyToCSSKey 555 ((StyleConstants)key); 556 if (cssKey != null) { 557 return super.addAttribute(old, cssKey, cssValue); 558 } 559 } 560 } 561 return super.addAttribute(old, key, value); 562 } 563 564 574 public AttributeSet addAttributes(AttributeSet old, AttributeSet attr) { 575 if (!(attr instanceof HTMLDocument.TaggedAttributeSet )) { 576 old = removeHTMLTags(old, attr); 577 } 578 return super.addAttributes(old, convertAttributeSet(attr)); 579 } 580 581 591 public AttributeSet removeAttribute(AttributeSet old, Object key) { 592 if (key instanceof StyleConstants) { 593 HTML.Tag tag = HTML.getTagForStyleConstantsKey( 594 (StyleConstants)key); 595 if (tag != null) { 596 old = super.removeAttribute(old, tag); 597 } 598 599 Object cssKey = css.styleConstantsKeyToCSSKey((StyleConstants)key); 600 if (cssKey != null) { 601 return super.removeAttribute(old, cssKey); 602 } 603 } 604 return super.removeAttribute(old, key); 605 } 606 607 617 public AttributeSet removeAttributes(AttributeSet old, Enumeration<?> names) { 618 return super.removeAttributes(old, names); 622 } 623 624 634 public AttributeSet removeAttributes(AttributeSet old, AttributeSet attrs) { 635 if (old != attrs) { 636 old = removeHTMLTags(old, attrs); 637 } 638 return super.removeAttributes(old, convertAttributeSet(attrs)); 639 } 640 641 651 protected SmallAttributeSet createSmallAttributeSet(AttributeSet a) { 652 return new SmallConversionSet(a); 653 } 654 655 667 protected MutableAttributeSet createLargeAttributeSet(AttributeSet a) { 668 return new LargeConversionSet(a); 669 } 670 671 675 private AttributeSet removeHTMLTags(AttributeSet old, AttributeSet attr) { 676 if (!(attr instanceof LargeConversionSet) && 677 !(attr instanceof SmallConversionSet)) { 678 Enumeration names = attr.getAttributeNames(); 679 680 while (names.hasMoreElements()) { 681 Object key = names.nextElement(); 682 683 if (key instanceof StyleConstants) { 684 HTML.Tag tag = HTML.getTagForStyleConstantsKey( 685 (StyleConstants)key); 686 687 if (tag != null && old.isDefined(tag)) { 688 old = super.removeAttribute(old, tag); 689 } 690 } 691 } 692 } 693 return old; 694 } 695 696 702 AttributeSet convertAttributeSet(AttributeSet a) { 703 if ((a instanceof LargeConversionSet) || 704 (a instanceof SmallConversionSet)) { 705 return a; 707 } 708 Enumeration names = a.getAttributeNames(); 712 while (names.hasMoreElements()) { 713 Object name = names.nextElement(); 714 if (name instanceof StyleConstants) { 715 MutableAttributeSet converted = new LargeConversionSet(); 718 Enumeration keys = a.getAttributeNames(); 719 while (keys.hasMoreElements()) { 720 Object key = keys.nextElement(); 721 Object cssValue = null; 722 if (key instanceof StyleConstants) { 723 Object cssKey = css.styleConstantsKeyToCSSKey 725 ((StyleConstants)key); 726 if (cssKey != null) { 727 Object value = a.getAttribute(key); 728 cssValue = css.styleConstantsValueToCSSValue 729 ((StyleConstants)key, value); 730 if (cssValue != null) { 731 converted.addAttribute(cssKey, cssValue); 732 } 733 } 734 } 735 if (cssValue == null) { 736 converted.addAttribute(key, a.getAttribute(key)); 737 } 738 } 739 return converted; 740 } 741 } 742 return a; 743 } 744 745 749 class LargeConversionSet extends SimpleAttributeSet { 750 751 756 public LargeConversionSet(AttributeSet source) { 757 super(source); 758 } 759 760 public LargeConversionSet() { 761 super(); 762 } 763 764 771 public boolean isDefined(Object key) { 772 if (key instanceof StyleConstants) { 773 Object cssKey = css.styleConstantsKeyToCSSKey 774 ((StyleConstants)key); 775 if (cssKey != null) { 776 return super.isDefined(cssKey); 777 } 778 } 779 return super.isDefined(key); 780 } 781 782 789 public Object getAttribute(Object key) { 790 if (key instanceof StyleConstants) { 791 Object cssKey = css.styleConstantsKeyToCSSKey 792 ((StyleConstants)key); 793 if (cssKey != null) { 794 Object value = super.getAttribute(cssKey); 795 if (value != null) { 796 return css.cssValueToStyleConstantsValue 797 ((StyleConstants)key, value); 798 } 799 } 800 } 801 return super.getAttribute(key); 802 } 803 } 804 805 809 class SmallConversionSet extends SmallAttributeSet { 810 811 816 public SmallConversionSet(AttributeSet attrs) { 817 super(attrs); 818 } 819 820 827 public boolean isDefined(Object key) { 828 if (key instanceof StyleConstants) { 829 Object cssKey = css.styleConstantsKeyToCSSKey 830 ((StyleConstants)key); 831 if (cssKey != null) { 832 return super.isDefined(cssKey); 833 } 834 } 835 return super.isDefined(key); 836 } 837 838 845 public Object getAttribute(Object key) { 846 if (key instanceof StyleConstants) { 847 Object cssKey = css.styleConstantsKeyToCSSKey 848 ((StyleConstants)key); 849 if (cssKey != null) { 850 Object value = super.getAttribute(cssKey); 851 if (value != null) { 852 return css.cssValueToStyleConstantsValue 853 ((StyleConstants)key, value); 854 } 855 } 856 } 857 return super.getAttribute(key); 858 } 859 } 860 861 863 866 public Font getFont(AttributeSet a) { 867 return css.getFont(this, a, 12, this); 868 } 869 870 878 public Color getForeground(AttributeSet a) { 879 Color c = css.getColor(a, CSS.Attribute.COLOR); 880 if (c == null) { 881 return Color.black; 882 } 883 return c; 884 } 885 886 894 public Color getBackground(AttributeSet a) { 895 return css.getColor(a, CSS.Attribute.BACKGROUND_COLOR); 896 } 897 898 902 public BoxPainter getBoxPainter(AttributeSet a) { 903 return new BoxPainter(a, css, this); 904 } 905 906 910 public ListPainter getListPainter(AttributeSet a) { 911 return new ListPainter(a, this); 912 } 913 914 917 public void setBaseFontSize(int sz) { 918 css.setBaseFontSize(sz); 919 } 920 921 926 public void setBaseFontSize(String size) { 927 css.setBaseFontSize(size); 928 } 929 930 public static int getIndexOfSize(float pt) { 931 return CSS.getIndexOfSize(pt, sizeMapDefault); 932 } 933 934 937 public float getPointSize(int index) { 938 return css.getPointSize(index, this); 939 } 940 941 945 public float getPointSize(String size) { 946 return css.getPointSize(size, this); 947 } 948 949 955 public Color stringToColor(String string) { 956 return CSS.stringToColor(string); 957 } 958 959 963 ImageIcon getBackgroundImage(AttributeSet attr) { 964 Object value = attr.getAttribute(CSS.Attribute.BACKGROUND_IMAGE); 965 966 if (value != null) { 967 return ((CSS.BackgroundImage )value).getImage(getBase()); 968 } 969 return null; 970 } 971 972 981 void addRule(String [] selector, AttributeSet declaration, 982 boolean isLinked) { 983 int n = selector.length; 984 StringBuffer sb = new StringBuffer (); 985 sb.append(selector[0]); 986 for (int counter = 1; counter < n; counter++) { 987 sb.append(' '); 988 sb.append(selector[counter]); 989 } 990 String selectorName = sb.toString(); 991 Style rule = getStyle(selectorName); 992 if (rule == null) { 993 Style altRule = addStyle(selectorName, null); 999 synchronized(this) { 1000 SelectorMapping mapping = getRootSelectorMapping(); 1001 for (int i = n - 1; i >= 0; i--) { 1002 mapping = mapping.getChildSelectorMapping 1003 (selector[i], true); 1004 } 1005 rule = mapping.getStyle(); 1006 if (rule == null) { 1007 rule = altRule; 1008 mapping.setStyle(rule); 1009 refreshResolvedRules(selectorName, selector, rule, 1010 mapping.getSpecificity()); 1011 } 1012 } 1013 } 1014 if (isLinked) { 1015 rule = getLinkedStyle(rule); 1016 } 1017 rule.addAttributes(declaration); 1018 } 1019 1020 1025 1029 private synchronized void linkStyleSheetAt(StyleSheet ss, int index) { 1030 if (resolvedStyles.size() > 0) { 1031 Enumeration values = resolvedStyles.elements(); 1032 while (values.hasMoreElements()) { 1033 ResolvedStyle rule = (ResolvedStyle)values.nextElement(); 1034 rule.insertExtendedStyleAt(ss.getRule(rule.getName()), 1035 index); 1036 } 1037 } 1038 } 1039 1040 1045 private synchronized void unlinkStyleSheet(StyleSheet ss, int index) { 1046 if (resolvedStyles.size() > 0) { 1047 Enumeration values = resolvedStyles.elements(); 1048 while (values.hasMoreElements()) { 1049 ResolvedStyle rule = (ResolvedStyle)values.nextElement(); 1050 rule.removeExtendedStyleAt(index); 1051 } 1052 } 1053 } 1054 1055 1058 1059 String [] getSimpleSelectors(String selector) { 1060 selector = cleanSelectorString(selector); 1061 SearchBuffer sb = SearchBuffer.obtainSearchBuffer(); 1062 Vector selectors = sb.getVector(); 1063 int lastIndex = 0; 1064 int length = selector.length(); 1065 while (lastIndex != -1) { 1066 int newIndex = selector.indexOf(' ', lastIndex); 1067 if (newIndex != -1) { 1068 selectors.addElement(selector.substring(lastIndex, newIndex)); 1069 if (++newIndex == length) { 1070 lastIndex = -1; 1071 } 1072 else { 1073 lastIndex = newIndex; 1074 } 1075 } 1076 else { 1077 selectors.addElement(selector.substring(lastIndex)); 1078 lastIndex = -1; 1079 } 1080 } 1081 String [] retValue = new String [selectors.size()]; 1082 selectors.copyInto(retValue); 1083 SearchBuffer.releaseSearchBuffer(sb); 1084 return retValue; 1085 } 1086 1087 1091 String cleanSelectorString(String selector) { 1092 boolean lastWasSpace = true; 1093 for (int counter = 0, maxCounter = selector.length(); 1094 counter < maxCounter; counter++) { 1095 switch(selector.charAt(counter)) { 1096 case ' ': 1097 if (lastWasSpace) { 1098 return _cleanSelectorString(selector); 1099 } 1100 lastWasSpace = true; 1101 break; 1102 case '\n': 1103 case '\r': 1104 case '\t': 1105 return _cleanSelectorString(selector); 1106 default: 1107 lastWasSpace = false; 1108 } 1109 } 1110 if (lastWasSpace) { 1111 return _cleanSelectorString(selector); 1112 } 1113 return selector; 1115 } 1116 1117 1121 private String _cleanSelectorString(String selector) { 1122 SearchBuffer sb = SearchBuffer.obtainSearchBuffer(); 1123 StringBuffer buff = sb.getStringBuffer(); 1124 boolean lastWasSpace = true; 1125 int lastIndex = 0; 1126 char[] chars = selector.toCharArray(); 1127 int numChars = chars.length; 1128 String retValue = null; 1129 try { 1130 for (int counter = 0; counter < numChars; counter++) { 1131 switch(chars[counter]) { 1132 case ' ': 1133 if (!lastWasSpace) { 1134 lastWasSpace = true; 1135 if (lastIndex < counter) { 1136 buff.append(chars, lastIndex, 1137 1 + counter - lastIndex); 1138 } 1139 } 1140 lastIndex = counter + 1; 1141 break; 1142 case '\n': 1143 case '\r': 1144 case '\t': 1145 if (!lastWasSpace) { 1146 lastWasSpace = true; 1147 if (lastIndex < counter) { 1148 buff.append(chars, lastIndex, 1149 counter - lastIndex); 1150 buff.append(' '); 1151 } 1152 } 1153 lastIndex = counter + 1; 1154 break; 1155 default: 1156 lastWasSpace = false; 1157 break; 1158 } 1159 } 1160 if (lastWasSpace && buff.length() > 0) { 1161 buff.setLength(buff.length() - 1); 1163 } 1164 else if (lastIndex < numChars) { 1165 buff.append(chars, lastIndex, numChars - lastIndex); 1166 } 1167 retValue = buff.toString(); 1168 } 1169 finally { 1170 SearchBuffer.releaseSearchBuffer(sb); 1171 } 1172 return retValue; 1173 } 1174 1175 1179 private SelectorMapping getRootSelectorMapping() { 1180 return selectorMapping; 1181 } 1182 1183 1190 static int getSpecificity(String selector) { 1191 int specificity = 0; 1192 boolean lastWasSpace = true; 1193 1194 for (int counter = 0, maxCounter = selector.length(); 1195 counter < maxCounter; counter++) { 1196 switch(selector.charAt(counter)) { 1197 case '.': 1198 specificity += 100; 1199 break; 1200 case '#': 1201 specificity += 10000; 1202 break; 1203 case ' ': 1204 lastWasSpace = true; 1205 break; 1206 default: 1207 if (lastWasSpace) { 1208 lastWasSpace = false; 1209 specificity += 1; 1210 } 1211 } 1212 } 1213 return specificity; 1214 } 1215 1216 1220 private Style getLinkedStyle(Style localStyle) { 1221 Style retStyle = (Style)localStyle.getResolveParent(); 1228 if (retStyle == null) { 1229 retStyle = addStyle(null, null); 1230 localStyle.setResolveParent(retStyle); 1231 } 1232 return retStyle; 1233 } 1234 1235 1239 private synchronized Style getResolvedStyle(String selector, 1240 Vector elements, 1241 HTML.Tag t) { 1242 Style retStyle = (Style)resolvedStyles.get(selector); 1243 if (retStyle == null) { 1244 retStyle = createResolvedStyle(selector, elements, t); 1245 } 1246 return retStyle; 1247 } 1248 1249 1253 private synchronized Style getResolvedStyle(String selector) { 1254 Style retStyle = (Style)resolvedStyles.get(selector); 1255 if (retStyle == null) { 1256 retStyle = createResolvedStyle(selector); 1257 } 1258 return retStyle; 1259 } 1260 1261 1266 private void addSortedStyle(SelectorMapping mapping, Vector elements) { 1267 int size = elements.size(); 1268 1269 if (size > 0) { 1270 int specificity = mapping.getSpecificity(); 1271 1272 for (int counter = 0; counter < size; counter++) { 1273 if (specificity >= ((SelectorMapping)elements.elementAt 1274 (counter)).getSpecificity()) { 1275 elements.insertElementAt(mapping, counter); 1276 return; 1277 } 1278 } 1279 } 1280 elements.addElement(mapping); 1281 } 1282 1283 1288 private synchronized void getStyles(SelectorMapping parentMapping, 1289 Vector styles, 1290 String [] tags, String [] ids, String [] classes, 1291 int index, int numElements, 1292 Hashtable alreadyChecked) { 1293 if (alreadyChecked.contains(parentMapping)) { 1295 return; 1296 } 1297 alreadyChecked.put(parentMapping, parentMapping); 1298 Style style = parentMapping.getStyle(); 1299 if (style != null) { 1300 addSortedStyle(parentMapping, styles); 1301 } 1302 for (int counter = index; counter < numElements; counter++) { 1303 String tagString = tags[counter]; 1304 if (tagString != null) { 1305 SelectorMapping childMapping = parentMapping. 1306 getChildSelectorMapping(tagString, false); 1307 if (childMapping != null) { 1308 getStyles(childMapping, styles, tags, ids, classes, 1309 counter + 1, numElements, alreadyChecked); 1310 } 1311 if (classes[counter] != null) { 1312 String className = classes[counter]; 1313 childMapping = parentMapping.getChildSelectorMapping( 1314 tagString + "." + className, false); 1315 if (childMapping != null) { 1316 getStyles(childMapping, styles, tags, ids, classes, 1317 counter + 1, numElements, alreadyChecked); 1318 } 1319 childMapping = parentMapping.getChildSelectorMapping( 1320 "." + className, false); 1321 if (childMapping != null) { 1322 getStyles(childMapping, styles, tags, ids, classes, 1323 counter + 1, numElements, alreadyChecked); 1324 } 1325 } 1326 if (ids[counter] != null) { 1327 String idName = ids[counter]; 1328 childMapping = parentMapping.getChildSelectorMapping( 1329 tagString + "#" + idName, false); 1330 if (childMapping != null) { 1331 getStyles(childMapping, styles, tags, ids, classes, 1332 counter + 1, numElements, alreadyChecked); 1333 } 1334 childMapping = parentMapping.getChildSelectorMapping( 1335 "#" + idName, false); 1336 if (childMapping != null) { 1337 getStyles(childMapping, styles, tags, ids, classes, 1338 counter + 1, numElements, alreadyChecked); 1339 } 1340 } 1341 } 1342 } 1343 } 1344 1345 1349 private synchronized Style createResolvedStyle(String selector, 1350 String [] tags, 1351 String [] ids, String [] classes) { 1352 SearchBuffer sb = SearchBuffer.obtainSearchBuffer(); 1353 Vector tempVector = sb.getVector(); 1354 Hashtable tempHashtable = sb.getHashtable(); 1355 try { 1358 SelectorMapping mapping = getRootSelectorMapping(); 1359 int numElements = tags.length; 1360 String tagString = tags[0]; 1361 SelectorMapping childMapping = mapping.getChildSelectorMapping( 1362 tagString, false); 1363 if (childMapping != null) { 1364 getStyles(childMapping, tempVector, tags, ids, classes, 1, 1365 numElements, tempHashtable); 1366 } 1367 if (classes[0] != null) { 1368 String className = classes[0]; 1369 childMapping = mapping.getChildSelectorMapping( 1370 tagString + "." + className, false); 1371 if (childMapping != null) { 1372 getStyles(childMapping, tempVector, tags, ids, classes, 1, 1373 numElements, tempHashtable); 1374 } 1375 childMapping = mapping.getChildSelectorMapping( 1376 "." + className, false); 1377 if (childMapping != null) { 1378 getStyles(childMapping, tempVector, tags, ids, classes, 1379 1, numElements, tempHashtable); 1380 } 1381 } 1382 if (ids[0] != null) { 1383 String idName = ids[0]; 1384 childMapping = mapping.getChildSelectorMapping( 1385 tagString + "#" + idName, false); 1386 if (childMapping != null) { 1387 getStyles(childMapping, tempVector, tags, ids, classes, 1388 1, numElements, tempHashtable); 1389 } 1390 childMapping = mapping.getChildSelectorMapping( 1391 "#" + idName, false); 1392 if (childMapping != null) { 1393 getStyles(childMapping, tempVector, tags, ids, classes, 1394 1, numElements, tempHashtable); 1395 } 1396 } 1397 int numLinkedSS = (linkedStyleSheets != null) ? 1400 linkedStyleSheets.size() : 0; 1401 int numStyles = tempVector.size(); 1402 AttributeSet[] attrs = new AttributeSet[numStyles + numLinkedSS]; 1403 for (int counter = 0; counter < numStyles; counter++) { 1404 attrs[counter] = ((SelectorMapping)tempVector. 1405 elementAt(counter)).getStyle(); 1406 } 1407 for (int counter = 0; counter < numLinkedSS; counter++) { 1409 AttributeSet attr = ((StyleSheet )linkedStyleSheets. 1410 elementAt(counter)).getRule(selector); 1411 if (attr == null) { 1412 attrs[counter + numStyles] = SimpleAttributeSet.EMPTY; 1413 } 1414 else { 1415 attrs[counter + numStyles] = attr; 1416 } 1417 } 1418 ResolvedStyle retStyle = new ResolvedStyle(selector, attrs, 1419 numStyles); 1420 resolvedStyles.put(selector, retStyle); 1421 return retStyle; 1422 } 1423 finally { 1424 SearchBuffer.releaseSearchBuffer(sb); 1425 } 1426 } 1427 1428 1439 private Style createResolvedStyle(String selector, Vector elements, 1440 HTML.Tag t) { 1441 int numElements = elements.size(); 1442 String tags[] = new String [numElements]; 1445 String ids[] = new String [numElements]; 1446 String classes[] = new String [numElements]; 1447 for (int counter = 0; counter < numElements; counter++) { 1448 Element e = (Element)elements.elementAt(counter); 1449 AttributeSet attr = e.getAttributes(); 1450 if (counter == 0 && e.isLeaf()) { 1451 Object testAttr = attr.getAttribute(t); 1453 if (testAttr instanceof AttributeSet) { 1454 attr = (AttributeSet)testAttr; 1455 } 1456 else { 1457 attr = null; 1458 } 1459 } 1460 if (attr != null) { 1461 HTML.Tag tag = (HTML.Tag )attr.getAttribute(StyleConstants. 1462 NameAttribute); 1463 if (tag != null) { 1464 tags[counter] = tag.toString(); 1465 } 1466 else { 1467 tags[counter] = null; 1468 } 1469 if (attr.isDefined(HTML.Attribute.CLASS)) { 1470 classes[counter] = attr.getAttribute 1471 (HTML.Attribute.CLASS).toString(); 1472 } 1473 else { 1474 classes[counter] = null; 1475 } 1476 if (attr.isDefined(HTML.Attribute.ID)) { 1477 ids[counter] = attr.getAttribute(HTML.Attribute.ID). 1478 toString(); 1479 } 1480 else { 1481 ids[counter] = null; 1482 } 1483 } 1484 else { 1485 tags[counter] = ids[counter] = classes[counter] = null; 1486 } 1487 } 1488 tags[0] = t.toString(); 1489 return createResolvedStyle(selector, tags, ids, classes); 1490 } 1491 1492 1497 private Style createResolvedStyle(String selector) { 1498 SearchBuffer sb = SearchBuffer.obtainSearchBuffer(); 1499 Vector elements = sb.getVector(); 1501 try { 1502 boolean done; 1503 int dotIndex = 0; 1504 int spaceIndex = 0; 1505 int poundIndex = 0; 1506 int lastIndex = 0; 1507 int length = selector.length(); 1508 while (lastIndex < length) { 1509 if (dotIndex == lastIndex) { 1510 dotIndex = selector.indexOf('.', lastIndex); 1511 } 1512 if (poundIndex == lastIndex) { 1513 poundIndex = selector.indexOf('#', lastIndex); 1514 } 1515 spaceIndex = selector.indexOf(' ', lastIndex); 1516 if (spaceIndex == -1) { 1517 spaceIndex = length; 1518 } 1519 if (dotIndex != -1 && poundIndex != -1 && 1520 dotIndex < spaceIndex && poundIndex < spaceIndex) { 1521 if (poundIndex < dotIndex) { 1522 if (lastIndex == poundIndex) { 1524 elements.addElement(""); 1525 } 1526 else { 1527 elements.addElement(selector.substring(lastIndex, 1528 poundIndex)); 1529 } 1530 if ((dotIndex + 1) < spaceIndex) { 1531 elements.addElement(selector.substring 1532 (dotIndex + 1, spaceIndex)); 1533 } 1534 else { 1535 elements.addElement(null); 1536 } 1537 if ((poundIndex + 1) == dotIndex) { 1538 elements.addElement(null); 1539 } 1540 else { 1541 elements.addElement(selector.substring 1542 (poundIndex + 1, dotIndex)); 1543 } 1544 } 1545 else if(poundIndex < spaceIndex) { 1546 if (lastIndex == dotIndex) { 1548 elements.addElement(""); 1549 } 1550 else { 1551 elements.addElement(selector.substring(lastIndex, 1552 dotIndex)); 1553 } 1554 if ((dotIndex + 1) < poundIndex) { 1555 elements.addElement(selector.substring 1556 (dotIndex + 1, poundIndex)); 1557 } 1558 else { 1559 elements.addElement(null); 1560 } 1561 if ((poundIndex + 1) == spaceIndex) { 1562 elements.addElement(null); 1563 } 1564 else { 1565 elements.addElement(selector.substring 1566 (poundIndex + 1, spaceIndex)); 1567 } 1568 } 1569 dotIndex = poundIndex = spaceIndex + 1; 1570 } 1571 else if (dotIndex != -1 && dotIndex < spaceIndex) { 1572 if (dotIndex == lastIndex) { 1574 elements.addElement(""); 1575 } 1576 else { 1577 elements.addElement(selector.substring(lastIndex, 1578 dotIndex)); 1579 } 1580 if ((dotIndex + 1) == spaceIndex) { 1581 elements.addElement(null); 1582 } 1583 else { 1584 elements.addElement(selector.substring(dotIndex + 1, 1585 spaceIndex)); 1586 } 1587 elements.addElement(null); 1588 dotIndex = spaceIndex + 1; 1589 } 1590 else if (poundIndex != -1 && poundIndex < spaceIndex) { 1591 if (poundIndex == lastIndex) { 1593 elements.addElement(""); 1594 } 1595 else { 1596 elements.addElement(selector.substring(lastIndex, 1597 poundIndex)); 1598 } 1599 elements.addElement(null); 1600 if ((poundIndex + 1) == spaceIndex) { 1601 elements.addElement(null); 1602 } 1603 else { 1604 elements.addElement(selector.substring(poundIndex + 1, 1605 spaceIndex)); 1606 } 1607 poundIndex = spaceIndex + 1; 1608 } 1609 else { 1610 elements.addElement(selector.substring(lastIndex, 1612 spaceIndex)); 1613 elements.addElement(null); 1614 elements.addElement(null); 1615 } 1616 lastIndex = spaceIndex + 1; 1617 } 1618 int total = elements.size(); 1620 int numTags = total / 3; 1621 String [] tags = new String [numTags]; 1622 String [] ids = new String [numTags]; 1623 String [] classes = new String [numTags]; 1624 for (int index = 0, eIndex = total - 3; index < numTags; 1625 index++, eIndex -= 3) { 1626 tags[index] = (String )elements.elementAt(eIndex); 1627 classes[index] = (String )elements.elementAt(eIndex + 1); 1628 ids[index] = (String )elements.elementAt(eIndex + 2); 1629 } 1630 return createResolvedStyle(selector, tags, ids, classes); 1631 } 1632 finally { 1633 SearchBuffer.releaseSearchBuffer(sb); 1634 } 1635 } 1636 1637 1642 private synchronized void refreshResolvedRules(String selectorName, 1643 String [] selector, 1644 Style newStyle, 1645 int specificity) { 1646 if (resolvedStyles.size() > 0) { 1647 Enumeration values = resolvedStyles.elements(); 1648 while (values.hasMoreElements()) { 1649 ResolvedStyle style = (ResolvedStyle)values.nextElement(); 1650 if (style.matches(selectorName)) { 1651 style.insertStyle(newStyle, specificity); 1652 } 1653 } 1654 } 1655 } 1656 1657 1658 1665 private static class SearchBuffer { 1666 1668 static Stack searchBuffers = new Stack(); 1669 Vector vector = null; 1671 StringBuffer stringBuffer = null; 1672 Hashtable hashtable = null; 1673 1674 1678 static SearchBuffer obtainSearchBuffer() { 1679 SearchBuffer sb; 1680 try { 1681 if(!searchBuffers.empty()) { 1682 sb = (SearchBuffer)searchBuffers.pop(); 1683 } else { 1684 sb = new SearchBuffer(); 1685 } 1686 } catch (EmptyStackException ese) { 1687 sb = new SearchBuffer(); 1688 } 1689 return sb; 1690 } 1691 1692 1696 static void releaseSearchBuffer(SearchBuffer sb) { 1697 sb.empty(); 1698 searchBuffers.push(sb); 1699 } 1700 1701 StringBuffer getStringBuffer() { 1702 if (stringBuffer == null) { 1703 stringBuffer = new StringBuffer (); 1704 } 1705 return stringBuffer; 1706 } 1707 1708 Vector getVector() { 1709 if (vector == null) { 1710 vector = new Vector(); 1711 } 1712 return vector; 1713 } 1714 1715 Hashtable getHashtable() { 1716 if (hashtable == null) { 1717 hashtable = new Hashtable(); 1718 } 1719 return hashtable; 1720 } 1721 1722 void empty() { 1723 if (stringBuffer != null) { 1724 stringBuffer.setLength(0); 1725 } 1726 if (vector != null) { 1727 vector.removeAllElements(); 1728 } 1729 if (hashtable != null) { 1730 hashtable.clear(); 1731 } 1732 } 1733 } 1734 1735 1736 static final Border noBorder = new EmptyBorder(0,0,0,0); 1737 1738 1749 public static class BoxPainter implements Serializable { 1750 1751 BoxPainter(AttributeSet a, CSS css, StyleSheet ss) { 1752 this.ss = ss; 1753 this.css = css; 1754 border = getBorder(a); 1755 binsets = border.getBorderInsets(null); 1756 topMargin = getLength(CSS.Attribute.MARGIN_TOP, a); 1757 bottomMargin = getLength(CSS.Attribute.MARGIN_BOTTOM, a); 1758 leftMargin = getLength(CSS.Attribute.MARGIN_LEFT, a); 1759 rightMargin = getLength(CSS.Attribute.MARGIN_RIGHT, a); 1760 bg = ss.getBackground(a); 1761 if (ss.getBackgroundImage(a) != null) { 1762 bgPainter = new BackgroundImagePainter(a, css, ss); 1763 } 1764 } 1765 1766 1771 Border getBorder(AttributeSet a) { 1772 Border b = noBorder; 1773 Object o = a.getAttribute(CSS.Attribute.BORDER_STYLE); 1774 if (o != null) { 1775 String bstyle = o.toString(); 1776 int bw = (int) getLength(CSS.Attribute.BORDER_TOP_WIDTH, a); 1777 if (bw > 0) { 1778 if (bstyle.equals("inset")) { 1779 Color c = getBorderColor(a); 1780 b = new BevelBorder(BevelBorder.LOWERED, c.brighter(), c.darker()); 1781 } else if (bstyle.equals("outset")) { 1782 Color c = getBorderColor(a); 1783 b = new BevelBorder(BevelBorder.RAISED, c.brighter(), c.darker()); 1784 } else if (bstyle.equals("solid")) { 1785 Color c = getBorderColor(a); 1786 b = new LineBorder(c); 1787 } 1788 } 1789 } 1790 return b; 1791 } 1792 1793 1799 Color getBorderColor(AttributeSet a) { 1800 Color color = css.getColor(a, CSS.Attribute.BORDER_COLOR); 1801 if (color == null) { 1802 color = css.getColor(a, CSS.Attribute.COLOR); 1803 if (color == null) { 1804 return Color.black; 1805 } 1806 } 1807 return color; 1808 } 1809 1810 1822 public float getInset(int side, View v) { 1823 AttributeSet a = v.getAttributes(); 1824 float inset = 0; 1825 switch(side) { 1826 case View.LEFT: 1827 inset += getOrientationMargin(HorizontalMargin.LEFT, 1828 leftMargin, a, isLeftToRight(v)); 1829 inset += binsets.left; 1830 inset += getLength(CSS.Attribute.PADDING_LEFT, a); 1831 break; 1832 case View.RIGHT: 1833 inset += getOrientationMargin(HorizontalMargin.RIGHT, 1834 rightMargin, a, isLeftToRight(v)); 1835 inset += binsets.right; 1836 inset += getLength(CSS.Attribute.PADDING_RIGHT, a); 1837 break; 1838 case View.TOP: 1839 inset += topMargin; 1840 inset += binsets.top; 1841 inset += getLength(CSS.Attribute.PADDING_TOP, a); 1842 break; 1843 case View.BOTTOM: 1844 inset += bottomMargin; 1845 inset += binsets.bottom; 1846 inset += getLength(CSS.Attribute.PADDING_BOTTOM, a); 1847 break; 1848 default: 1849 throw new IllegalArgumentException ("Invalid side: " + side); 1850 } 1851 return inset; 1852 } 1853 1854 1870 public void paint(Graphics g, float x, float y, float w, float h, View v) { 1871 1875 float dx = 0; 1876 float dy = 0; 1877 float dw = 0; 1878 float dh = 0; 1879 AttributeSet a = v.getAttributes(); 1880 boolean isLeftToRight = isLeftToRight(v); 1881 float localLeftMargin = getOrientationMargin(HorizontalMargin.LEFT, 1882 leftMargin, 1883 a, isLeftToRight); 1884 float localRightMargin = getOrientationMargin(HorizontalMargin.RIGHT, 1885 rightMargin, 1886 a, isLeftToRight); 1887 if (!(v instanceof HTMLEditorKit.HTMLFactory.BodyBlockView )) { 1888 dx = localLeftMargin; 1889 dy = topMargin; 1890 dw = -(localLeftMargin + localRightMargin); 1891 dh = -(topMargin + bottomMargin); 1892 } 1893 if (bg != null) { 1894 g.setColor(bg); 1895 g.fillRect((int) (x + dx), 1896 (int) (y + dy), 1897 (int) (w + dw), 1898 (int) (h + dh)); 1899 } 1900 if (bgPainter != null) { 1901 bgPainter.paint(g, x + dx, y + dy, w + dw, h + dh, v); 1902 } 1903 x += localLeftMargin; 1904 y += topMargin; 1905 w -= localLeftMargin + localRightMargin; 1906 h -= topMargin + bottomMargin; 1907 border.paintBorder(null, g, (int) x, (int) y, (int) w, (int) h); 1908 } 1909 1910 float getLength(CSS.Attribute key, AttributeSet a) { 1911 return css.getLength(a, key, ss); 1912 } 1913 1914 static boolean isLeftToRight(View v) { 1915 boolean ret = true; 1916 if (isOrientationAware(v)) { 1917 Container container = null; 1918 if (v != null && (container = v.getContainer()) != null) { 1919 ret = container.getComponentOrientation().isLeftToRight(); 1920 } 1921 } 1922 return ret; 1923 } 1924 1925 1931 static boolean isOrientationAware(View v) { 1932 boolean ret = false; 1933 AttributeSet attr = null; 1934 Object obj = null; 1935 if (v != null 1936 && (attr = v.getElement().getAttributes()) != null 1937 && (obj = attr.getAttribute(StyleConstants.NameAttribute)) instanceof HTML.Tag 1938 && (obj == HTML.Tag.DIR 1939 || obj == HTML.Tag.MENU 1940 || obj == HTML.Tag.UL 1941 || obj == HTML.Tag.OL)) { 1942 ret = true; 1943 } 1944 1945 return ret; 1946 } 1947 1948 static enum HorizontalMargin { LEFT, RIGHT }; 1949 1950 1964 float getOrientationMargin(HorizontalMargin side, float cssMargin, 1965 AttributeSet a, boolean isLeftToRight) { 1966 float margin = cssMargin; 1967 float orientationMargin = cssMargin; 1968 Object cssMarginValue = null; 1969 switch (side) { 1970 case RIGHT: 1971 { 1972 orientationMargin = (isLeftToRight) ? 1973 getLength(CSS.Attribute.MARGIN_RIGHT_LTR, a) : 1974 getLength(CSS.Attribute.MARGIN_RIGHT_RTL, a); 1975 cssMarginValue = a.getAttribute(CSS.Attribute.MARGIN_RIGHT); 1976 } 1977 break; 1978 case LEFT : 1979 { 1980 orientationMargin = (isLeftToRight) ? 1981 getLength(CSS.Attribute.MARGIN_LEFT_LTR, a) : 1982 getLength(CSS.Attribute.MARGIN_LEFT_RTL, a); 1983 cssMarginValue = a.getAttribute(CSS.Attribute.MARGIN_LEFT); 1984 } 1985 break; 1986 } 1987 1988 if (cssMarginValue == null 1989 && orientationMargin != Integer.MIN_VALUE) { 1990 margin = orientationMargin; 1991 } 1992 return margin; 1993 } 1994 1995 float topMargin; 1996 float bottomMargin; 1997 float leftMargin; 1998 float rightMargin; 1999 short marginFlags; 2002 Border border; 2003 Insets binsets; 2004 CSS css; 2005 StyleSheet ss; 2006 Color bg; 2007 BackgroundImagePainter bgPainter; 2008 } 2009 2010 2017 public static class ListPainter implements Serializable { 2018 2019 ListPainter(AttributeSet attr, StyleSheet ss) { 2020 this.ss = ss; 2021 2022 String imgstr = (String )attr.getAttribute(CSS.Attribute. 2023 LIST_STYLE_IMAGE); 2024 type = null; 2025 if (imgstr != null && !imgstr.equals("none")) { 2026 String tmpstr = null; 2027 try { 2028 StringTokenizer st = new StringTokenizer(imgstr, "()"); 2029 if (st.hasMoreTokens()) 2030 tmpstr = st.nextToken(); 2031 if (st.hasMoreTokens()) 2032 tmpstr = st.nextToken(); 2033 URL u = new URL(tmpstr); 2034 img = new ImageIcon (u); 2035 } catch (MalformedURLException e) { 2036 if (tmpstr != null && ss != null && ss.getBase() != null) { 2037 try { 2038 URL u = new URL(ss.getBase(), tmpstr); 2039 img = new ImageIcon (u); 2040 } catch (MalformedURLException murle) { 2041 img = null; 2042 } 2043 } 2044 else { 2045 img = null; 2046 } 2047 } 2048 } 2049 2050 2051 if (img == null) { 2052 type = (CSS.Value )attr.getAttribute(CSS.Attribute. 2053 LIST_STYLE_TYPE); 2054 } 2055 start = 1; 2056 2057 paintRect = new Rectangle(); 2058 } 2059 2060 2068 private CSS.Value getChildType(View childView) { 2069 CSS.Value childtype = (CSS.Value )childView.getAttributes(). 2070 getAttribute(CSS.Attribute.LIST_STYLE_TYPE); 2071 2072 if (childtype == null) { 2073 if (type == null) { 2074 View v = childView.getParent(); 2076 HTMLDocument doc = (HTMLDocument )v.getDocument(); 2077 if (doc.matchNameAttribute(v.getElement().getAttributes(), 2078 HTML.Tag.OL)) { 2079 childtype = CSS.Value.DECIMAL; 2080 } else { 2081 childtype = CSS.Value.DISC; 2082 } 2083 } else { 2084 childtype = type; 2085 } 2086 } 2087 return childtype; 2088 } 2089 2090 2093 private void getStart(View parent) { 2094 checkedForStart = true; 2095 Element element = parent.getElement(); 2096 if (element != null) { 2097 AttributeSet attr = element.getAttributes(); 2098 Object startValue; 2099 if (attr != null && attr.isDefined(HTML.Attribute.START) && 2100 (startValue = attr.getAttribute 2101 (HTML.Attribute.START)) != null && 2102 (startValue instanceof String )) { 2103 2104 try { 2105 start = Integer.parseInt((String )startValue); 2106 } 2107 catch (NumberFormatException nfe) {} 2108 } 2109 } 2110 } 2111 2112 2119 private int getRenderIndex(View parentView, int childIndex) { 2120 if (!checkedForStart) { 2121 getStart(parentView); 2122 } 2123 int retIndex = childIndex; 2124 for (int counter = childIndex; counter >= 0; counter--) { 2125 AttributeSet as = parentView.getElement().getElement(counter). 2126 getAttributes(); 2127 if (as.getAttribute(StyleConstants.NameAttribute) != 2128 HTML.Tag.LI) { 2129 retIndex--; 2130 } else if (as.isDefined(HTML.Attribute.VALUE)) { 2131 Object value = as.getAttribute(HTML.Attribute.VALUE); 2132 if (value != null && 2133 (value instanceof String )) { 2134 try { 2135 int iValue = Integer.parseInt((String )value); 2136 return retIndex - counter + iValue; 2137 } 2138 catch (NumberFormatException nfe) {} 2139 } 2140 } 2141 } 2142 return retIndex + start; 2143 } 2144 2145 2158 public void paint(Graphics g, float x, float y, float w, float h, View v, int item) { 2159 View cv = v.getView(item); 2160 Object name = cv.getElement().getAttributes().getAttribute 2161 (StyleConstants.NameAttribute); 2162 if (!(name instanceof HTML.Tag ) || 2165 name != HTML.Tag.LI) { 2166 return; 2167 } 2168 isLeftToRight = 2170 cv.getContainer().getComponentOrientation().isLeftToRight(); 2171 2172 float align = 0; 2178 if (cv.getViewCount() > 0) { 2179 View pView = cv.getView(0); 2180 Object cName = pView.getElement().getAttributes(). 2181 getAttribute(StyleConstants.NameAttribute); 2182 if ((cName == HTML.Tag.P || cName == HTML.Tag.IMPLIED) && 2183 pView.getViewCount() > 0) { 2184 paintRect.setBounds((int)x, (int)y, (int)w, (int)h); 2185 Shape shape = cv.getChildAllocation(0, paintRect); 2186 if (shape != null && (shape = pView.getView(0). 2187 getChildAllocation(0, shape)) != null) { 2188 Rectangle rect = (shape instanceof Rectangle) ? 2189 (Rectangle)shape : shape.getBounds(); 2190 2191 align = pView.getView(0).getAlignment(View.Y_AXIS); 2192 y = rect.y; 2193 h = rect.height; 2194 } 2195 } 2196 } 2197 2198 if (ss != null) { 2200 g.setColor(ss.getForeground(cv.getAttributes())); 2201 } else { 2202 g.setColor(Color.black); 2203 } 2204 2205 if (img != null) { 2206 drawIcon(g, (int) x, (int) y, (int) w, (int) h, align, 2207 v.getContainer()); 2208 return; 2209 } 2210 CSS.Value childtype = getChildType(cv); 2211 Font font = ((StyledDocument)cv.getDocument()). 2212 getFont(cv.getAttributes()); 2213 if (font != null) { 2214 g.setFont(font); 2215 } 2216 if (childtype == CSS.Value.SQUARE || childtype == CSS.Value.CIRCLE 2217 || childtype == CSS.Value.DISC) { 2218 drawShape(g, childtype, (int) x, (int) y, 2219 (int) w, (int) h, align); 2220 } else if (childtype == CSS.Value.DECIMAL) { 2221 drawLetter(g, '1', (int) x, (int) y, (int) w, (int) h, align, 2222 getRenderIndex(v, item)); 2223 } else if (childtype == CSS.Value.LOWER_ALPHA) { 2224 drawLetter(g, 'a', (int) x, (int) y, (int) w, (int) h, align, 2225 getRenderIndex(v, item)); 2226 } else if (childtype == CSS.Value.UPPER_ALPHA) { 2227 drawLetter(g, 'A', (int) x, (int) y, (int) w, (int) h, align, 2228 getRenderIndex(v, item)); 2229 } else if (childtype == CSS.Value.LOWER_ROMAN) { 2230 drawLetter(g, 'i', (int) x, (int) y, (int) w, (int) h, align, 2231 getRenderIndex(v, item)); 2232 } else if (childtype == CSS.Value.UPPER_ROMAN) { 2233 drawLetter(g, 'I', (int) x, (int) y, (int) w, (int) h, align, 2234 getRenderIndex(v, item)); 2235 } 2236 } 2237 2238 2248 void drawIcon(Graphics g, int ax, int ay, int aw, int ah, 2249 float align, Component c) { 2250 int gap = isLeftToRight ? - (img.getIconWidth() + bulletgap) : 2252 (aw + bulletgap); 2253 int x = ax + gap; 2254 int y = Math.max(ay, ay + (int)(align * ah) -img.getIconHeight()); 2255 2256 img.paintIcon(c, g, x, y); 2257 } 2258 2259 2270 void drawShape(Graphics g, CSS.Value type, int ax, int ay, int aw, 2271 int ah, float align) { 2272 int gap = isLeftToRight ? - (bulletgap + 8) : (aw + bulletgap); 2274 int x = ax + gap; 2275 int y = Math.max(ay, ay + (int)(align * ah) - 8); 2276 2277 if (type == CSS.Value.SQUARE) { 2278 g.drawRect(x, y, 8, 8); 2279 } else if (type == CSS.Value.CIRCLE) { 2280 g.drawOval(x, y, 8, 8); 2281 } else { 2282 g.fillOval(x, y, 8, 8); 2283 } 2284 } 2285 2286 2297 void drawLetter(Graphics g, char letter, int ax, int ay, int aw, 2298 int ah, float align, int index) { 2299 String str = formatItemNum(index, letter); 2300 str = isLeftToRight ? str + "." : "." + str; 2301 FontMetrics fm = SwingUtilities2.getFontMetrics(null, g); 2302 int stringwidth = SwingUtilities2.stringWidth(null, fm, str); 2303 int gap = isLeftToRight ? - (stringwidth + bulletgap) : 2304 (aw + bulletgap); 2305 int x = ax + gap; 2306 int y = Math.max(ay + fm.getAscent(), ay + (int)(ah * align)); 2307 SwingUtilities2.drawString(null, g, str, x, y); 2308 } 2309 2310 2317 String formatItemNum(int itemNum, char type) { 2318 String numStyle = "1"; 2319 2320 boolean uppercase = false; 2321 2322 String formattedNum; 2323 2324 switch (type) { 2325 case '1': 2326 default: 2327 formattedNum = String.valueOf(itemNum); 2328 break; 2329 2330 case 'A': 2331 uppercase = true; 2332 case 'a': 2334 formattedNum = formatAlphaNumerals(itemNum); 2335 break; 2336 2337 case 'I': 2338 uppercase = true; 2339 case 'i': 2341 formattedNum = formatRomanNumerals(itemNum); 2342 } 2343 2344 if (uppercase) { 2345 formattedNum = formattedNum.toUpperCase(); 2346 } 2347 2348 return formattedNum; 2349 } 2350 2351 2356 String formatAlphaNumerals(int itemNum) { 2357 String result = ""; 2358 2359 if (itemNum > 26) { 2360 result = formatAlphaNumerals(itemNum / 26) + 2361 formatAlphaNumerals(itemNum % 26); 2362 } else { 2363 result = String.valueOf((char)('a' + itemNum - 1)); 2365 } 2366 2367 return result; 2368 } 2369 2370 2371 static final char romanChars[][] = { 2372 {'i', 'v'}, 2373 {'x', 'l' }, 2374 {'c', 'd' }, 2375 {'m', '?' }, 2376 }; 2377 2378 2383 String formatRomanNumerals(int num) { 2384 return formatRomanNumerals(0, num); 2385 } 2386 2387 2392 String formatRomanNumerals(int level, int num) { 2393 if (num < 10) { 2394 return formatRomanDigit(level, num); 2395 } else { 2396 return formatRomanNumerals(level + 1, num / 10) + 2397 formatRomanDigit(level, num % 10); 2398 } 2399 } 2400 2401 2402 2408 String formatRomanDigit(int level, int digit) { 2409 String result = ""; 2410 if (digit == 9) { 2411 result = result + romanChars[level][0]; 2412 result = result + romanChars[level + 1][0]; 2413 return result; 2414 } else if (digit == 4) { 2415 result = result + romanChars[level][0]; 2416 result = result + romanChars[level][1]; 2417 return result; 2418 } else if (digit >= 5) { 2419 result = result + romanChars[level][1]; 2420 digit -= 5; 2421 } 2422 2423 for (int i = 0; i < digit; i++) { 2424 result = result + romanChars[level][0]; 2425 } 2426 2427 return result; 2428 } 2429 2430 private Rectangle paintRect; 2431 private boolean checkedForStart; 2432 private int start; 2433 private CSS.Value type; 2434 URL imageurl; 2435 private StyleSheet ss = null; 2436 Icon img = null; 2437 private int bulletgap = 5; 2438 private boolean isLeftToRight; 2439 } 2440 2441 2442 2445 static class BackgroundImagePainter implements Serializable { 2446 ImageIcon backgroundImage; 2447 float hPosition; 2448 float vPosition; 2449 short flags; 2452 private int paintX; 2454 private int paintY; 2455 private int paintMaxX; 2456 private int paintMaxY; 2457 2458 BackgroundImagePainter(AttributeSet a, CSS css, StyleSheet ss) { 2459 backgroundImage = ss.getBackgroundImage(a); 2460 CSS.BackgroundPosition pos = (CSS.BackgroundPosition )a.getAttribute 2462 (CSS.Attribute.BACKGROUND_POSITION); 2463 if (pos != null) { 2464 hPosition = pos.getHorizontalPosition(); 2465 vPosition = pos.getVerticalPosition(); 2466 if (pos.isHorizontalPositionRelativeToSize()) { 2467 flags |= 4; 2468 } 2469 else if (pos.isHorizontalPositionRelativeToSize()) { 2470 hPosition *= css.getFontSize(a, 12, ss); 2471 } 2472 if (pos.isVerticalPositionRelativeToSize()) { 2473 flags |= 8; 2474 } 2475 else if (pos.isVerticalPositionRelativeToFontSize()) { 2476 vPosition *= css.getFontSize(a, 12, ss); 2477 } 2478 } 2479 CSS.Value repeats = (CSS.Value )a.getAttribute(CSS.Attribute. 2481 BACKGROUND_REPEAT); 2482 if (repeats == null || repeats == CSS.Value.BACKGROUND_REPEAT) { 2483 flags |= 3; 2484 } 2485 else if (repeats == CSS.Value.BACKGROUND_REPEAT_X) { 2486 flags |= 1; 2487 } 2488 else if (repeats == CSS.Value.BACKGROUND_REPEAT_Y) { 2489 flags |= 2; 2490 } 2491 } 2492 2493 void paint(Graphics g, float x, float y, float w, float h, View v) { 2494 Rectangle clip = g.getClipRect(); 2495 if (clip != null) { 2496 g.clipRect((int)x, (int)y, (int)w, (int)h); 2499 } 2500 if ((flags & 3) == 0) { 2501 int width = backgroundImage.getIconWidth(); 2503 int height = backgroundImage.getIconWidth(); 2504 if ((flags & 4) == 4) { 2505 paintX = (int)(x + w * hPosition - 2506 (float)width * hPosition); 2507 } 2508 else { 2509 paintX = (int)x + (int)hPosition; 2510 } 2511 if ((flags & 8) == 8) { 2512 paintY = (int)(y + h * vPosition - 2513 (float)height * vPosition); 2514 } 2515 else { 2516 paintY = (int)y + (int)vPosition; 2517 } 2518 if (clip == null || 2519 !((paintX + width <= clip.x) || 2520 (paintY + height <= clip.y) || 2521 (paintX >= clip.x + clip.width) || 2522 (paintY >= clip.y + clip.height))) { 2523 backgroundImage.paintIcon(null, g, paintX, paintY); 2524 } 2525 } 2526 else { 2527 int width = backgroundImage.getIconWidth(); 2528 int height = backgroundImage.getIconHeight(); 2529 if (width > 0 && height > 0) { 2530 paintX = (int)x; 2531 paintY = (int)y; 2532 paintMaxX = (int)(x + w); 2533 paintMaxY = (int)(y + h); 2534 if (updatePaintCoordinates(clip, width, height)) { 2535 while (paintX < paintMaxX) { 2536 int ySpot = paintY; 2537 while (ySpot < paintMaxY) { 2538 backgroundImage.paintIcon(null, g, paintX, 2539 ySpot); 2540 ySpot += height; 2541 } 2542 paintX += width; 2543 } 2544 } 2545 } 2546 } 2547 if (clip != null) { 2548 g.setClip(clip.x, clip.y, clip.width, clip.height); 2550 } 2551 } 2552 2553 private boolean updatePaintCoordinates 2554 (Rectangle clip, int width, int height){ 2555 if ((flags & 3) == 1) { 2556 paintMaxY = paintY + 1; 2557 } 2558 else if ((flags & 3) == 2) { 2559 paintMaxX = paintX + 1; 2560 } 2561 if (clip != null) { 2562 if ((flags & 3) == 1 && ((paintY + height <= clip.y) || 2563 (paintY > clip.y + clip.height))) { 2564 return false; 2566 } 2567 if ((flags & 3) == 2 && ((paintX + width <= clip.x) || 2568 (paintX > clip.x + clip.width))) { 2569 return false; 2571 } 2572 if ((flags & 1) == 1) { 2573 if ((clip.x + clip.width) < paintMaxX) { 2574 if ((clip.x + clip.width - paintX) % width == 0) { 2575 paintMaxX = clip.x + clip.width; 2576 } 2577 else { 2578 paintMaxX = ((clip.x + clip.width - paintX) / 2579 width + 1) * width + paintX; 2580 } 2581 } 2582 if (clip.x > paintX) { 2583 paintX = (clip.x - paintX) / width * width + paintX; 2584 } 2585 } 2586 if ((flags & 2) == 2) { 2587 if ((clip.y + clip.height) < paintMaxY) { 2588 if ((clip.y + clip.height - paintY) % height == 0) { 2589 paintMaxY = clip.y + clip.height; 2590 } 2591 else { 2592 paintMaxY = ((clip.y + clip.height - paintY) / 2593 height + 1) * height + paintY; 2594 } 2595 } 2596 if (clip.y > paintY) { 2597 paintY = (clip.y - paintY) / height * height + paintY; 2598 } 2599 } 2600 } 2601 return true; 2603 } 2604 } 2605 2606 2607 2612 class ViewAttributeSet extends MuxingAttributeSet { 2613 ViewAttributeSet(View v) { 2614 host = v; 2615 2616 Document doc = v.getDocument(); 2619 SearchBuffer sb = SearchBuffer.obtainSearchBuffer(); 2620 Vector muxList = sb.getVector(); 2621 try { 2622 if (doc instanceof HTMLDocument ) { 2623 StyleSheet styles = StyleSheet.this; 2624 Element elem = v.getElement(); 2625 AttributeSet a = elem.getAttributes(); 2626 AttributeSet htmlAttr = styles.translateHTMLToCSS(a); 2627 2628 if (htmlAttr.getAttributeCount() != 0) { 2629 muxList.addElement(htmlAttr); 2630 } 2631 if (elem.isLeaf()) { 2632 Enumeration keys = a.getAttributeNames(); 2633 while (keys.hasMoreElements()) { 2634 Object key = keys.nextElement(); 2635 if (key instanceof HTML.Tag ) { 2636 if ((HTML.Tag )key == HTML.Tag.A) { 2637 Object o = a.getAttribute((HTML.Tag )key); 2638 2651 if (o != null && o instanceof AttributeSet) { 2652 AttributeSet attr = (AttributeSet)o; 2653 if (attr.getAttribute(HTML.Attribute.HREF) == null) { 2654 continue; 2655 } 2656 } 2657 } 2658 AttributeSet cssRule = styles.getRule((HTML.Tag ) key, elem); 2659 if (cssRule != null) { 2660 muxList.addElement(cssRule); 2661 } 2662 } 2663 } 2664 } else { 2665 HTML.Tag t = (HTML.Tag ) a.getAttribute 2666 (StyleConstants.NameAttribute); 2667 AttributeSet cssRule = styles.getRule(t, elem); 2668 if (cssRule != null) { 2669 muxList.addElement(cssRule); 2670 } 2671 } 2672 } 2673 AttributeSet[] attrs = new AttributeSet[muxList.size()]; 2674 muxList.copyInto(attrs); 2675 setAttributes(attrs); 2676 } 2677 finally { 2678 SearchBuffer.releaseSearchBuffer(sb); 2679 } 2680 } 2681 2682 2684 2694 public boolean isDefined(Object key) { 2695 if (key instanceof StyleConstants) { 2696 Object cssKey = css.styleConstantsKeyToCSSKey 2697 ((StyleConstants)key); 2698 if (cssKey != null) { 2699 key = cssKey; 2700 } 2701 } 2702 return super.isDefined(key); 2703 } 2704 2705 2714 public Object getAttribute(Object key) { 2715 if (key instanceof StyleConstants) { 2716 Object cssKey = css.styleConstantsKeyToCSSKey 2717 ((StyleConstants)key); 2718 if (cssKey != null) { 2719 Object value = doGetAttribute(cssKey); 2720 if (value instanceof CSS.CssValue ) { 2721 return ((CSS.CssValue )value).toStyleConstants 2722 ((StyleConstants)key, host); 2723 } 2724 } 2725 } 2726 return doGetAttribute(key); 2727 } 2728 2729 Object doGetAttribute(Object key) { 2730 Object retValue = super.getAttribute(key); 2731 if (retValue != null) { 2732 return retValue; 2733 } 2734 if (key instanceof CSS.Attribute ) { 2737 CSS.Attribute css = (CSS.Attribute ) key; 2738 if (css.isInherited()) { 2739 AttributeSet parent = getResolveParent(); 2740 if (parent != null) 2741 return parent.getAttribute(key); 2742 } 2743 } 2744 return null; 2745 } 2746 2747 2754 public AttributeSet getResolveParent() { 2755 if (host == null) { 2756 return null; 2757 } 2758 View parent = host.getParent(); 2759 return (parent != null) ? parent.getAttributes() : null; 2760 } 2761 2762 2763 View host; 2764 } 2765 2766 2767 2772 static class ResolvedStyle extends MuxingAttributeSet implements 2777 Serializable, Style { 2778 ResolvedStyle(String name, AttributeSet[] attrs, int extendedIndex) { 2779 super(attrs); 2780 this.name = name; 2781 this.extendedIndex = extendedIndex; 2782 } 2783 2784 2790 synchronized void insertStyle(Style style, int specificity) { 2791 AttributeSet[] attrs = getAttributes(); 2792 int maxCounter = attrs.length; 2793 int counter = 0; 2794 for (;counter < extendedIndex; counter++) { 2795 if (specificity > getSpecificity(((Style)attrs[counter]). 2796 getName())) { 2797 break; 2798 } 2799 } 2800 insertAttributeSetAt(style, counter); 2801 extendedIndex++; 2802 } 2803 2804 2808 synchronized void removeStyle(Style style) { 2809 AttributeSet[] attrs = getAttributes(); 2810 2811 for (int counter = attrs.length - 1; counter >= 0; counter--) { 2812 if (attrs[counter] == style) { 2813 removeAttributeSetAt(counter); 2814 if (counter < extendedIndex) { 2815 extendedIndex--; 2816 } 2817 break; 2818 } 2819 } 2820 } 2821 2822 2826 synchronized void insertExtendedStyleAt(Style attr, int index) { 2827 insertAttributeSetAt(attr, extendedIndex + index); 2828 } 2829 2830 2834 synchronized void addExtendedStyle(Style attr) { 2835 insertAttributeSetAt(attr, getAttributes().length); 2836 } 2837 2838 2842 synchronized void removeExtendedStyleAt(int index) { 2843 removeAttributeSetAt(extendedIndex + index); 2844 } 2845 2846 2851 protected boolean matches(String selector) { 2852 int sLast = selector.length(); 2853 2854 if (sLast == 0) { 2855 return false; 2856 } 2857 int thisLast = name.length(); 2858 int sCurrent = selector.lastIndexOf(' '); 2859 int thisCurrent = name.lastIndexOf(' '); 2860 if (sCurrent >= 0) { 2861 sCurrent++; 2862 } 2863 if (thisCurrent >= 0) { 2864 thisCurrent++; 2865 } 2866 if (!matches(selector, sCurrent, sLast, thisCurrent, thisLast)) { 2867 return false; 2868 } 2869 while (sCurrent != -1) { 2870 sLast = sCurrent - 1; 2871 sCurrent = selector.lastIndexOf(' ', sLast - 1); 2872 if (sCurrent >= 0) { 2873 sCurrent++; 2874 } 2875 boolean match = false; 2876 while (!match && thisCurrent != -1) { 2877 thisLast = thisCurrent - 1; 2878 thisCurrent = name.lastIndexOf(' ', thisLast - 1); 2879 if (thisCurrent >= 0) { 2880 thisCurrent++; 2881 } 2882 match = matches(selector, sCurrent, sLast, thisCurrent, 2883 thisLast); 2884 } 2885 if (!match) { 2886 return false; 2887 } 2888 } 2889 return true; 2890 } 2891 2892 2897 boolean matches(String selector, int sCurrent, int sLast, 2898 int thisCurrent, int thisLast) { 2899 sCurrent = Math.max(sCurrent, 0); 2900 thisCurrent = Math.max(thisCurrent, 0); 2901 int thisDotIndex = boundedIndexOf(name, '.', thisCurrent, 2902 thisLast); 2903 int thisPoundIndex = boundedIndexOf(name, '#', thisCurrent, 2904 thisLast); 2905 int sDotIndex = boundedIndexOf(selector, '.', sCurrent, sLast); 2906 int sPoundIndex = boundedIndexOf(selector, '#', sCurrent, sLast); 2907 if (sDotIndex != -1) { 2908 if (thisDotIndex == -1) { 2912 return false; 2913 } 2914 if (sCurrent == sDotIndex) { 2915 if ((thisLast - thisDotIndex) != (sLast - sDotIndex) || 2916 !selector.regionMatches(sCurrent, name, thisDotIndex, 2917 (thisLast - thisDotIndex))) { 2918 return false; 2919 } 2920 } 2921 else { 2922 if ((sLast - sCurrent) != (thisLast - thisCurrent) || 2924 !selector.regionMatches(sCurrent, name, thisCurrent, 2925 (thisLast - thisCurrent))) { 2926 return false; 2927 } 2928 } 2929 return true; 2930 } 2931 if (sPoundIndex != -1) { 2932 if (thisPoundIndex == -1) { 2936 return false; 2937 } 2938 if (sCurrent == sPoundIndex) { 2939 if ((thisLast - thisPoundIndex) !=(sLast - sPoundIndex) || 2940 !selector.regionMatches(sCurrent, name, thisPoundIndex, 2941 (thisLast - thisPoundIndex))) { 2942 return false; 2943 } 2944 } 2945 else { 2946 if ((sLast - sCurrent) != (thisLast - thisCurrent) || 2948 !selector.regionMatches(sCurrent, name, thisCurrent, 2949 (thisLast - thisCurrent))) { 2950 return false; 2951 } 2952 } 2953 return true; 2954 } 2955 if (thisDotIndex != -1) { 2956 return (((thisDotIndex - thisCurrent) == (sLast - sCurrent)) && 2958 selector.regionMatches(sCurrent, name, thisCurrent, 2959 thisDotIndex - thisCurrent)); 2960 } 2961 if (thisPoundIndex != -1) { 2962 return (((thisPoundIndex - thisCurrent) ==(sLast - sCurrent))&& 2964 selector.regionMatches(sCurrent, name, thisCurrent, 2965 thisPoundIndex - thisCurrent)); 2966 } 2967 return (((thisLast - thisCurrent) == (sLast - sCurrent)) && 2969 selector.regionMatches(sCurrent, name, thisCurrent, 2970 thisLast - thisCurrent)); 2971 } 2972 2973 2978 int boundedIndexOf(String string, char search, int start, 2979 int end) { 2980 int retValue = string.indexOf(search, start); 2981 if (retValue >= end) { 2982 return -1; 2983 } 2984 return retValue; 2985 } 2986 2987 public void addAttribute(Object name, Object value) {} 2988 public void addAttributes(AttributeSet attributes) {} 2989 public void removeAttribute(Object name) {} 2990 public void removeAttributes(Enumeration<?> names) {} 2991 public void removeAttributes(AttributeSet attributes) {} 2992 public void setResolveParent(AttributeSet parent) {} 2993 public String getName() {return name;} 2994 public void addChangeListener(ChangeListener l) {} 2995 public void removeChangeListener(ChangeListener l) {} 2996 public ChangeListener [] getChangeListeners() { 2997 return new ChangeListener [0]; 2998 } 2999 3000 3003 String name; 3004 3005 private int extendedIndex; 3006 } 3007 3008 3009 3017 static class SelectorMapping implements Serializable { 3018 public SelectorMapping(int specificity) { 3019 this.specificity = specificity; 3020 } 3021 3022 3025 public int getSpecificity() { 3026 return specificity; 3027 } 3028 3029 3032 public void setStyle(Style style) { 3033 this.style = style; 3034 } 3035 3036 3039 public Style getStyle() { 3040 return style; 3041 } 3042 3043 3049 public SelectorMapping getChildSelectorMapping(String selector, 3050 boolean create) { 3051 SelectorMapping retValue = null; 3052 3053 if (children != null) { 3054 retValue = (SelectorMapping)children.get(selector); 3055 } 3056 else if (create) { 3057 children = new HashMap(7); 3058 } 3059 if (retValue == null && create) { 3060 int specificity = getChildSpecificity(selector); 3061 3062 retValue = createChildSelectorMapping(specificity); 3063 children.put(selector, retValue); 3064 } 3065 return retValue; 3066 } 3067 3068 3072 protected SelectorMapping createChildSelectorMapping(int specificity) { 3073 return new SelectorMapping(specificity); 3074 } 3075 3076 3080 protected int getChildSpecificity(String selector) { 3081 char firstChar = selector.charAt(0); 3084 int specificity = getSpecificity(); 3085 3086 if (firstChar == '.') { 3087 specificity += 100; 3088 } 3089 else if (firstChar == '#') { 3090 specificity += 10000; 3091 } 3092 else { 3093 specificity += 1; 3094 if (selector.indexOf('.') != -1) { 3095 specificity += 100; 3096 } 3097 if (selector.indexOf('#') != -1) { 3098 specificity += 10000; 3099 } 3100 } 3101 return specificity; 3102 } 3103 3104 3107 private int specificity; 3108 3111 private Style style; 3112 3116 private HashMap children; 3117 } 3118 3119 3120 3122 final static int DEFAULT_FONT_SIZE = 3; 3123 3124 private CSS css; 3125 3126 3129 private SelectorMapping selectorMapping; 3130 3131 3133 private Hashtable resolvedStyles; 3134 3135 3137 private Vector linkedStyleSheets; 3138 3139 3140 private URL base; 3141 3142 3143 3149 class CssParser implements CSSParser.CSSParserCallback { 3150 3151 3154 public AttributeSet parseDeclaration(String string) { 3155 try { 3156 return parseDeclaration(new StringReader(string)); 3157 } catch (IOException ioe) {} 3158 return null; 3159 } 3160 3161 3164 public AttributeSet parseDeclaration(Reader r) throws IOException { 3165 parse(base, r, true, false); 3166 return declaration.copyAttributes(); 3167 } 3168 3169 3172 public void parse(URL base, Reader r, boolean parseDeclaration, 3173 boolean isLink) throws IOException { 3174 this.base = base; 3175 this.isLink = isLink; 3176 this.parsingDeclaration = parseDeclaration; 3177 declaration.removeAttributes(declaration); 3178 selectorTokens.removeAllElements(); 3179 selectors.removeAllElements(); 3180 propertyName = null; 3181 parser.parse(r, this, parseDeclaration); 3182 } 3183 3184 3188 3194 public void handleImport(String importString) { 3195 URL url = CSS.getURL(base, importString); 3196 if (url != null) { 3197 importStyleSheet(url); 3198 } 3199 } 3200 3201 3204 public void handleSelector(String selector) { 3205 selector = selector.toLowerCase(); 3206 3207 int length = selector.length(); 3208 3209 if (selector.endsWith(",")) { 3210 if (length > 1) { 3211 selector = selector.substring(0, length - 1); 3212 selectorTokens.addElement(selector); 3213 } 3214 addSelector(); 3215 } 3216 else if (length > 0) { 3217 selectorTokens.addElement(selector); 3218 } 3219 } 3220 3221 3224 public void startRule() { 3225 if (selectorTokens.size() > 0) { 3226 addSelector(); 3227 } 3228 propertyName = null; 3229 } 3230 3231 3234 public void handleProperty(String property) { 3235 propertyName = property; 3236 } 3237 3238 3241 public void handleValue(String value) { 3242 if (propertyName != null && value != null && value.length() > 0) { 3243 CSS.Attribute cssKey = CSS.getAttribute(propertyName); 3244 if (cssKey != null) { 3245 if (cssKey == CSS.Attribute.LIST_STYLE_IMAGE) { 3251 if (value != null && !value.equals("none")) { 3252 URL url = CSS.getURL(base, value); 3253 3254 if (url != null) { 3255 value = url.toString(); 3256 } 3257 } 3258 } 3259 addCSSAttribute(declaration, cssKey, value); 3260 } 3261 propertyName = null; 3262 } 3263 } 3264 3265 3268 public void endRule() { 3269 int n = selectors.size(); 3270 for (int i = 0; i < n; i++) { 3271 String [] selector = (String []) selectors.elementAt(i); 3272 if (selector.length > 0) { 3273 StyleSheet.this.addRule(selector, declaration, isLink); 3274 } 3275 } 3276 declaration.removeAttributes(declaration); 3277 selectors.removeAllElements(); 3278 } 3279 3280 private void addSelector() { 3281 String [] selector = new String [selectorTokens.size()]; 3282 selectorTokens.copyInto(selector); 3283 selectors.addElement(selector); 3284 selectorTokens.removeAllElements(); 3285 } 3286 3287 3288 Vector selectors = new Vector(); 3289 Vector selectorTokens = new Vector(); 3290 3291 String propertyName; 3292 MutableAttributeSet declaration = new SimpleAttributeSet(); 3293 3295 boolean parsingDeclaration; 3296 3297 boolean isLink; 3298 3299 URL base; 3300 CSSParser parser = new CSSParser (); 3301 } 3302 3303 void rebaseSizeMap(int base) { 3304 final int minimalFontSize = 4; 3305 sizeMap = new int[sizeMapDefault.length]; 3306 for (int i = 0; i < sizeMapDefault.length; i++) { 3307 sizeMap[i] = Math.max(base * sizeMapDefault[i] / 3308 sizeMapDefault[CSS.baseFontSizeIndex], 3309 minimalFontSize); 3310 } 3311 3312 } 3313 3314 int[] getSizeMap() { 3315 return sizeMap; 3316 } 3317 boolean isW3CLengthUnits() { 3318 return w3cLengthUnits; 3319 } 3320 3321 3325 static int sizeMapDefault[] = { 8, 10, 12, 14, 18, 24, 36 }; 3326 3327 private int sizeMap[] = sizeMapDefault; 3328 private boolean w3cLengthUnits = false; 3329} 3330 | Popular Tags |