1. /*
  2. * @(#)CSS.java 1.14 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.text.html;
  8. import java.awt.Color;
  9. import java.awt.Font;
  10. import java.io.*;
  11. import java.util.Enumeration;
  12. import java.util.Hashtable;
  13. import javax.swing.text.*;
  14. /**
  15. * Defines a set of
  16. * <a href="http://www.w3.org/TR/REC-CSS1">CSS attributes</a>
  17. * as a typesafe enumeration. The html View implementations use
  18. * css attributes to determine how they will render. This also defines
  19. * methods to map between CSS<->HTML<->StyleConstants.
  20. *
  21. * @author Timothy Prinzing
  22. * @version 1.14 11/29/01
  23. * @see StyleSheet
  24. */
  25. public class CSS {
  26. /**
  27. * Definitions to be used as a key on AttributeSet's
  28. * that might hold css attributes. Since this is a
  29. * closed set (i.e. defined exactly by the specification),
  30. * it is final and cannot be extended.
  31. */
  32. public static final class Attribute {
  33. private Attribute(String name, String defaultValue, boolean inherited) {
  34. this.name = name;
  35. this.defaultValue = defaultValue;
  36. this.inherited = inherited;
  37. }
  38. /**
  39. * The string representation of the attribute. This
  40. * should exactly match the string specified in the
  41. * css specification.
  42. */
  43. public String toString() {
  44. return name;
  45. }
  46. /**
  47. * Fetch the default value for the attribute.
  48. * If there is no default value (such as for
  49. * composite attributes), null will be returned.
  50. */
  51. public String getDefaultValue() {
  52. return defaultValue;
  53. }
  54. /**
  55. * Indicates if the attribute should be inherited
  56. * from the parent or not.
  57. */
  58. public boolean isInherited() {
  59. return inherited;
  60. }
  61. private String name;
  62. private String defaultValue;
  63. private boolean inherited;
  64. public static final Attribute BACKGROUND =
  65. new Attribute("background", null, false);
  66. public static final Attribute BACKGROUND_ATTACHMENT =
  67. new Attribute("background-attachment", "scroll", false);
  68. public static final Attribute BACKGROUND_COLOR =
  69. new Attribute("background-color", "transparent", false);
  70. public static final Attribute BACKGROUND_IMAGE =
  71. new Attribute("background-image", "none", false);
  72. public static final Attribute BACKGROUND_POSITION =
  73. new Attribute("background-position", null, false);
  74. public static final Attribute BACKGROUND_REPEAT =
  75. new Attribute("background-repeat", "repeat", false);
  76. public static final Attribute BORDER =
  77. new Attribute("border", null, false);
  78. public static final Attribute BORDER_BOTTOM =
  79. new Attribute("border-bottom", null, false);
  80. public static final Attribute BORDER_BOTTOM_WIDTH =
  81. new Attribute("border-bottom-width", "medium", false);
  82. public static final Attribute BORDER_COLOR =
  83. new Attribute("border-color", null, false);
  84. public static final Attribute BORDER_LEFT =
  85. new Attribute("border-left", null, false);
  86. public static final Attribute BORDER_LEFT_WIDTH =
  87. new Attribute("border-left-width", "medium", false);
  88. public static final Attribute BORDER_RIGHT =
  89. new Attribute("border-right", null, false);
  90. public static final Attribute BORDER_RIGHT_WIDTH =
  91. new Attribute("border-right-width", "medium", false);
  92. public static final Attribute BORDER_STYLE =
  93. new Attribute("border-style", "none", false);
  94. public static final Attribute BORDER_TOP =
  95. new Attribute("border-top", null, false);
  96. public static final Attribute BORDER_TOP_WIDTH =
  97. new Attribute("border-top-width", "medium", false);
  98. public static final Attribute BORDER_WIDTH =
  99. new Attribute("border-width", "medium", false);
  100. public static final Attribute CLEAR =
  101. new Attribute("clear", "none", false);
  102. public static final Attribute COLOR =
  103. new Attribute("color", null, true);
  104. public static final Attribute DISPLAY =
  105. new Attribute("display", "block", false);
  106. public static final Attribute FLOAT =
  107. new Attribute("float", "none", false);
  108. public static final Attribute FONT =
  109. new Attribute("font", null, true);
  110. public static final Attribute FONT_FAMILY =
  111. new Attribute("font-family", null, true);
  112. public static final Attribute FONT_SIZE =
  113. new Attribute("font-size", "medium", true);
  114. public static final Attribute FONT_STYLE =
  115. new Attribute("font-style", "normal", true);
  116. public static final Attribute FONT_VARIANT =
  117. new Attribute("font-variant", "normal", true);
  118. public static final Attribute FONT_WEIGHT =
  119. new Attribute("font-weight", "normal", true);
  120. public static final Attribute HEIGHT =
  121. new Attribute("height", "auto", false);
  122. public static final Attribute LETTER_SPACING =
  123. new Attribute("letter-spacing", "normal", true);
  124. public static final Attribute LINE_HEIGHT =
  125. new Attribute("line-height", "normal", true);
  126. public static final Attribute LIST_STYLE =
  127. new Attribute("list-style", null, true);
  128. public static final Attribute LIST_STYLE_IMAGE =
  129. new Attribute("list-style-image", "none", true);
  130. public static final Attribute LIST_STYLE_POSITION =
  131. new Attribute("list-style-position", "outside", true);
  132. public static final Attribute LIST_STYLE_TYPE =
  133. new Attribute("list-style-type", "disc", true);
  134. public static final Attribute MARGIN =
  135. new Attribute("margin", null, false);
  136. public static final Attribute MARGIN_BOTTOM =
  137. new Attribute("margin-bottom", "0", false);
  138. public static final Attribute MARGIN_LEFT =
  139. new Attribute("margin-left", "0", false);
  140. public static final Attribute MARGIN_RIGHT =
  141. new Attribute("margin-right", "0", false);
  142. public static final Attribute MARGIN_TOP =
  143. new Attribute("margin-top", "0", false);
  144. public static final Attribute PADDING =
  145. new Attribute("padding", null, false);
  146. public static final Attribute PADDING_BOTTOM =
  147. new Attribute("padding-bottom", "0", false);
  148. public static final Attribute PADDING_LEFT =
  149. new Attribute("padding-left", "0", false);
  150. public static final Attribute PADDING_RIGHT =
  151. new Attribute("padding-right", "0", false);
  152. public static final Attribute PADDING_TOP =
  153. new Attribute("padding-top", "0", false);
  154. public static final Attribute TEXT_ALIGN =
  155. new Attribute("text-align", null, true);
  156. public static final Attribute TEXT_DECORATION =
  157. new Attribute("text-decoration", "none", true);
  158. public static final Attribute TEXT_INDENT =
  159. new Attribute("text-indent", "0", true);
  160. public static final Attribute TEXT_TRANSFORM =
  161. new Attribute("text-transform", "none", true);
  162. public static final Attribute VERTICAL_ALIGN =
  163. new Attribute("vertical-align", "baseline", false);
  164. public static final Attribute WORD_SPACING =
  165. new Attribute("word-spacing", "normal", true);
  166. public static final Attribute WHITE_SPACE =
  167. new Attribute("whitespace", "normal", true);
  168. public static final Attribute WIDTH =
  169. new Attribute("width", "auto", false);
  170. // All possible css attribute keys.
  171. static final Attribute[] allAttributes = {
  172. BACKGROUND, BACKGROUND_ATTACHMENT, BACKGROUND_COLOR,
  173. BACKGROUND_IMAGE, BACKGROUND_POSITION, BACKGROUND_REPEAT,
  174. BORDER, BORDER_BOTTOM, BORDER_BOTTOM_WIDTH, BORDER_COLOR,
  175. BORDER_LEFT, BORDER_LEFT_WIDTH, BORDER_RIGHT, BORDER_RIGHT_WIDTH,
  176. BORDER_STYLE, BORDER_TOP, BORDER_TOP_WIDTH, BORDER_WIDTH,
  177. CLEAR, COLOR, DISPLAY, FLOAT, FONT, FONT_FAMILY, FONT_SIZE,
  178. FONT_STYLE, FONT_VARIANT, FONT_WEIGHT, HEIGHT, LETTER_SPACING,
  179. LINE_HEIGHT, LIST_STYLE, LIST_STYLE_IMAGE, LIST_STYLE_POSITION,
  180. LIST_STYLE_TYPE, MARGIN, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT,
  181. MARGIN_TOP, PADDING, PADDING_BOTTOM, PADDING_LEFT, PADDING_RIGHT,
  182. PADDING_TOP, TEXT_ALIGN, TEXT_DECORATION, TEXT_INDENT, TEXT_TRANSFORM,
  183. VERTICAL_ALIGN, WORD_SPACING, WHITE_SPACE, WIDTH
  184. };
  185. }
  186. static final class Value {
  187. private Value(String name) {
  188. this.name = name;
  189. }
  190. /**
  191. * The string representation of the attribute. This
  192. * should exactly match the string specified in the
  193. * css specification.
  194. */
  195. public String toString() {
  196. return name;
  197. }
  198. static final Value INHERITED = new Value("inherited");
  199. static final Value NONE = new Value("none");
  200. static final Value DOTTED = new Value("dotted");
  201. static final Value DASHED = new Value("dashed");
  202. static final Value SOLID = new Value("solid");
  203. static final Value DOUBLE = new Value("double");
  204. static final Value GROOVE = new Value("groove");
  205. static final Value RIDGE = new Value("ridge");
  206. static final Value INSET = new Value("inset");
  207. static final Value OUTSET = new Value("outset");
  208. // Lists.
  209. static final Value BLANK_LIST_ITEM = new Value("none");
  210. static final Value DISC = new Value("disc");
  211. static final Value CIRCLE = new Value("circle");
  212. static final Value SQUARE = new Value("square");
  213. static final Value DECIMAL = new Value("decimal");
  214. static final Value LOWER_ROMAN = new Value("lower-roman");
  215. static final Value UPPER_ROMAN = new Value("upper-roman");
  216. static final Value LOWER_ALPHA = new Value("lower-alpha");
  217. static final Value UPPER_ALPHA = new Value("upper-alpha");
  218. private String name;
  219. static final Value[] allValues = {
  220. INHERITED, NONE, DOTTED, DASHED, SOLID, DOUBLE, GROOVE,
  221. RIDGE, INSET, OUTSET, DISC, CIRCLE, SQUARE, DECIMAL,
  222. LOWER_ROMAN, UPPER_ROMAN, LOWER_ALPHA, UPPER_ALPHA,
  223. BLANK_LIST_ITEM
  224. };
  225. }
  226. public CSS() {
  227. baseFontSize = 3;
  228. // setup the css conversion table
  229. valueConvertor = new Hashtable();
  230. valueConvertor.put(CSS.Attribute.FONT_SIZE, new FontSize());
  231. valueConvertor.put(CSS.Attribute.FONT_FAMILY, new FontFamily());
  232. valueConvertor.put(CSS.Attribute.FONT_WEIGHT, new FontWeight());
  233. valueConvertor.put(CSS.Attribute.BORDER_STYLE, new BorderStyle());
  234. Object cv = new ColorValue();
  235. valueConvertor.put(CSS.Attribute.COLOR, cv);
  236. valueConvertor.put(CSS.Attribute.BACKGROUND_COLOR, cv);
  237. valueConvertor.put(CSS.Attribute.BORDER_COLOR, cv);
  238. Object lv = new LengthValue();
  239. valueConvertor.put(CSS.Attribute.MARGIN_TOP, lv);
  240. valueConvertor.put(CSS.Attribute.MARGIN_BOTTOM, lv);
  241. valueConvertor.put(CSS.Attribute.MARGIN_LEFT, lv);
  242. valueConvertor.put(CSS.Attribute.MARGIN_RIGHT, lv);
  243. valueConvertor.put(CSS.Attribute.PADDING_TOP, lv);
  244. valueConvertor.put(CSS.Attribute.PADDING_BOTTOM, lv);
  245. valueConvertor.put(CSS.Attribute.PADDING_LEFT, lv);
  246. valueConvertor.put(CSS.Attribute.PADDING_RIGHT, lv);
  247. valueConvertor.put(CSS.Attribute.BORDER_WIDTH, lv);
  248. valueConvertor.put(CSS.Attribute.BORDER_TOP_WIDTH, lv);
  249. valueConvertor.put(CSS.Attribute.BORDER_BOTTOM_WIDTH, lv);
  250. valueConvertor.put(CSS.Attribute.BORDER_LEFT_WIDTH, lv);
  251. valueConvertor.put(CSS.Attribute.BORDER_RIGHT_WIDTH, lv);
  252. valueConvertor.put(CSS.Attribute.TEXT_INDENT, lv);
  253. valueConvertor.put(CSS.Attribute.WIDTH, lv);
  254. valueConvertor.put(CSS.Attribute.HEIGHT, lv);
  255. Object sv = new StringValue();
  256. valueConvertor.put(CSS.Attribute.FONT_STYLE, sv);
  257. valueConvertor.put(CSS.Attribute.TEXT_DECORATION, sv);
  258. valueConvertor.put(CSS.Attribute.TEXT_ALIGN, sv);
  259. valueConvertor.put(CSS.Attribute.VERTICAL_ALIGN, sv);
  260. valueConvertor.put(CSS.Attribute.LIST_STYLE_TYPE, new ListType());
  261. Object generic = new CssValue();
  262. int n = CSS.Attribute.allAttributes.length;
  263. for (int i = 0; i < n; i++) {
  264. CSS.Attribute key = CSS.Attribute.allAttributes[i];
  265. if (valueConvertor.get(key) == null) {
  266. valueConvertor.put(key, generic);
  267. }
  268. }
  269. }
  270. /**
  271. * Sets the base font size. <code>sz</code> is a CSS value, and is
  272. * not necessarily the point size. Use getPointSize to determine the
  273. * point size corresponding to <code>sz</code>.
  274. */
  275. void setBaseFontSize(int sz) {
  276. if (sz < 1)
  277. baseFontSize = 0;
  278. else if (sz > 7)
  279. baseFontSize = 7;
  280. else
  281. baseFontSize = sz;
  282. }
  283. /**
  284. * Sets the base font size from the passed in string.
  285. */
  286. void setBaseFontSize(String size) {
  287. int relSize, absSize, diff;
  288. if (size != null) {
  289. if (size.startsWith("+")) {
  290. relSize = Integer.valueOf(size.substring(1)).intValue();
  291. setBaseFontSize(baseFontSize + relSize);
  292. } else if (size.startsWith("-")) {
  293. relSize = -Integer.valueOf(size.substring(1)).intValue();
  294. setBaseFontSize(baseFontSize + relSize);
  295. } else {
  296. setBaseFontSize(Integer.valueOf(size).intValue());
  297. }
  298. }
  299. }
  300. /**
  301. * Returns the base font size.
  302. */
  303. int getBaseFontSize() {
  304. return baseFontSize;
  305. }
  306. /**
  307. * Gets the internal CSS representation of <code>value</code> which is
  308. * a CSS value of the CSS attribute named <code>key</code>.
  309. */
  310. Object getInternalCSSValue(CSS.Attribute key, String value) {
  311. CssValue conv = (CssValue) valueConvertor.get(key);
  312. return conv.parseCssValue(value);
  313. }
  314. /**
  315. * Maps from a StyleConstants to a CSS Attribute.
  316. */
  317. Attribute styleConstantsKeyToCSSKey(StyleConstants sc) {
  318. return (Attribute)styleConstantToCssMap.get(sc);
  319. }
  320. /**
  321. * Maps from a StyleConstants value to a CSS value.
  322. */
  323. Object styleConstantsValueToCSSValue(StyleConstants sc,
  324. Object styleValue) {
  325. Object cssKey = styleConstantsKeyToCSSKey(sc);
  326. if (cssKey != null) {
  327. CssValue conv = (CssValue)valueConvertor.get(cssKey);
  328. return conv.fromStyleConstants(sc, styleValue);
  329. }
  330. return null;
  331. }
  332. /**
  333. * Converts the passed in CSS value to a StyleConstants value.
  334. * <code>key</code> identifies the CSS attribute being mapped.
  335. */
  336. Object cssValueToStyleConstantsValue(StyleConstants key, Object value) {
  337. if (value instanceof CssValue) {
  338. return ((CssValue)value).toStyleConstants((StyleConstants)key);
  339. }
  340. return null;
  341. }
  342. /**
  343. * Returns the font for the values in the passed in AttributeSet.
  344. * It is assumed the keys will be CSS.Attribute keys.
  345. * <code>sc</code> is the StyleContext that will be messaged to get
  346. * the font once the size, name and style have been determined.
  347. */
  348. Font getFont(StyleContext sc, AttributeSet a, int defaultSize) {
  349. // PENDING(prinz) this is a 1.1 based implementation, need to also
  350. // have a 1.2 version.
  351. FontSize sizeValue = (FontSize)a.getAttribute(CSS.Attribute.FONT_SIZE);
  352. int size = (sizeValue != null) ? (int) sizeValue.getValue(a) :
  353. defaultSize;
  354. /*
  355. * If the vertical alignment is set to either superscirpt or
  356. * subscript we reduce the font size by 2 points.
  357. */
  358. StringValue vAlignV = (StringValue)a.getAttribute
  359. (CSS.Attribute.VERTICAL_ALIGN);
  360. if ((vAlignV != null)) {
  361. String vAlign = vAlignV.toString();
  362. if ((vAlign.indexOf("sup") >= 0) ||
  363. (vAlign.indexOf("sub") >= 0)) {
  364. size -= 2;
  365. }
  366. }
  367. FontFamily familyValue = (FontFamily)a.getAttribute
  368. (CSS.Attribute.FONT_FAMILY);
  369. String family = (familyValue != null) ? familyValue.getValue() :
  370. "SansSerif";
  371. int style = Font.PLAIN;
  372. FontWeight weightValue = (FontWeight) a.getAttribute
  373. (CSS.Attribute.FONT_WEIGHT);
  374. if ((weightValue != null) && (weightValue.getValue() > 400)) {
  375. style |= Font.BOLD;
  376. }
  377. Object fs = a.getAttribute(CSS.Attribute.FONT_STYLE);
  378. if ((fs != null) && (fs.toString().indexOf("italic") >= 0)) {
  379. style |= Font.ITALIC;
  380. }
  381. Font f = sc.getFont(family, style, size);
  382. return f;
  383. }
  384. /**
  385. * Takes a set of attributes and turn it into a color
  386. * specification. This might be used to specify things
  387. * like brighter, more hue, etc.
  388. * This will return null if there is no value for <code>key</code>.
  389. *
  390. * @parram key CSS.Attribute identifying where color is stored.
  391. * @param a the set of attributes
  392. * @return the color
  393. */
  394. Color getColor(AttributeSet a, CSS.Attribute key) {
  395. ColorValue cv = (ColorValue) a.getAttribute(key);
  396. if (cv != null) {
  397. return cv.getValue();
  398. }
  399. return null;
  400. }
  401. /**
  402. * Returns the size of a font from the passed in string.
  403. *
  404. * @param size CSS string describing font size
  405. * @param baseFontSize size to use for relative units.
  406. */
  407. float getPointSize(String size) {
  408. int relSize, absSize, diff, index;
  409. if (size != null) {
  410. if (size.startsWith("+")) {
  411. relSize = Integer.valueOf(size.substring(1)).intValue();
  412. return getPointSize(baseFontSize + relSize);
  413. } else if (size.startsWith("-")) {
  414. relSize = -Integer.valueOf(size.substring(1)).intValue();
  415. return getPointSize(baseFontSize + relSize);
  416. } else {
  417. absSize = Integer.valueOf(size).intValue();
  418. return getPointSize(absSize);
  419. }
  420. }
  421. return 0;
  422. }
  423. /**
  424. * Returns the length of the attribute in <code>a</code> with
  425. * key <code>key</code>.
  426. */
  427. float getLength(AttributeSet a, CSS.Attribute key) {
  428. LengthValue lv = (LengthValue) a.getAttribute(key);
  429. float len = (lv != null) ? lv.getValue() : 0;
  430. return len;
  431. }
  432. /**
  433. * Convert a set of html attributes to an equivalent
  434. * set of css attributes.
  435. *
  436. * @param AttributeSet containing the HTML attributes.
  437. * @return AttributeSet containing the corresponding CSS attributes.
  438. * The AttributeSet will be empty if there are no mapping
  439. * CSS attributes.
  440. */
  441. AttributeSet translateHTMLToCSS(AttributeSet htmlAttrSet) {
  442. MutableAttributeSet cssAttrSet = new SimpleAttributeSet();
  443. Element elem = (Element)htmlAttrSet;
  444. HTML.Tag tag = getHTMLTag(htmlAttrSet);
  445. if ((tag == HTML.Tag.TD) || (tag == HTML.Tag.TH)) {
  446. // translate border width into the cells
  447. AttributeSet tableAttr = elem.getParentElement().
  448. getParentElement().getAttributes();
  449. translateAttribute(HTML.Attribute.BORDER, tableAttr, cssAttrSet);
  450. String pad = (String)tableAttr.getAttribute(HTML.Attribute.CELLPADDING);
  451. if (pad != null) {
  452. Object v = getInternalCSSValue(CSS.Attribute.PADDING_TOP, pad);
  453. cssAttrSet.addAttribute(CSS.Attribute.PADDING_TOP, v);
  454. cssAttrSet.addAttribute(CSS.Attribute.PADDING_BOTTOM, v);
  455. cssAttrSet.addAttribute(CSS.Attribute.PADDING_LEFT, v);
  456. cssAttrSet.addAttribute(CSS.Attribute.PADDING_RIGHT, v);
  457. }
  458. }
  459. if (elem.isLeaf()) {
  460. translateEmbeddedAttributes(htmlAttrSet, cssAttrSet);
  461. } else {
  462. translateAttributes(tag, htmlAttrSet, cssAttrSet);
  463. }
  464. return cssAttrSet;
  465. }
  466. private static final Hashtable attributeMap = new Hashtable();
  467. private static final Hashtable valueMap = new Hashtable();
  468. /**
  469. * The html/css size model has seven slots
  470. * that one can assign sizes to.
  471. */
  472. static int sizeMap[] = { 8, 10, 12, 14, 18, 24, 36 };
  473. /**
  474. * The hashtable and the static initalization block below,
  475. * set up a mapping from well-known HTML attributes to
  476. * CSS attributes. For the most part, there is a 1-1 mapping
  477. * between the two. However in the case of certain HTML
  478. * attributes for example HTML.Attribute.VSPACE or
  479. * HTML.Attribute.HSPACE, end up mapping to two CSS.Attribute's.
  480. * Therefore, the value associated with each HTML.Attribute.
  481. * key ends up being an array of CSS.Attribute.* objects.
  482. */
  483. private static final Hashtable htmlAttrToCssAttrMap = new Hashtable(20);
  484. /**
  485. * The hashtable and static initialization that follows sets
  486. * up a translation from StyleConstants (i.e. the <em>well known</em>
  487. * attributes) to the associated CSS attributes.
  488. */
  489. private static final Hashtable styleConstantToCssMap = new Hashtable(17);
  490. /** Maps from HTML value to a CSS value. Used in internal mapping. */
  491. private static final Hashtable htmlValueToCssValueMap = new Hashtable(8);
  492. /** Maps from CSS value (string) to internal value. */
  493. private static final Hashtable cssValueToInternalValueMap = new Hashtable(8);
  494. static {
  495. // load the attribute map
  496. for (int i = 0; i < Attribute.allAttributes.length; i++ ) {
  497. attributeMap.put(Attribute.allAttributes[i].toString(),
  498. Attribute.allAttributes[i]);
  499. }
  500. // load the value map
  501. for (int i = 0; i < Value.allValues.length; i++ ) {
  502. valueMap.put(Value.allValues[i].toString(),
  503. Value.allValues[i]);
  504. }
  505. htmlAttrToCssAttrMap.put(HTML.Attribute.COLOR,
  506. new CSS.Attribute[]{CSS.Attribute.COLOR});
  507. htmlAttrToCssAttrMap.put(HTML.Attribute.TEXT,
  508. new CSS.Attribute[]{CSS.Attribute.COLOR});
  509. htmlAttrToCssAttrMap.put(HTML.Attribute.CLEAR,
  510. new CSS.Attribute[]{CSS.Attribute.CLEAR});
  511. htmlAttrToCssAttrMap.put(HTML.Attribute.BACKGROUND,
  512. new CSS.Attribute[]{CSS.Attribute.BACKGROUND_IMAGE});
  513. htmlAttrToCssAttrMap.put(HTML.Attribute.BGCOLOR,
  514. new CSS.Attribute[]{CSS.Attribute.BACKGROUND_COLOR});
  515. htmlAttrToCssAttrMap.put(HTML.Attribute.WIDTH,
  516. new CSS.Attribute[]{CSS.Attribute.WIDTH});
  517. htmlAttrToCssAttrMap.put(HTML.Attribute.HEIGHT,
  518. new CSS.Attribute[]{CSS.Attribute.HEIGHT});
  519. htmlAttrToCssAttrMap.put(HTML.Attribute.BORDER,
  520. new CSS.Attribute[]{CSS.Attribute.BORDER_WIDTH});
  521. htmlAttrToCssAttrMap.put(HTML.Attribute.CELLPADDING,
  522. new CSS.Attribute[]{CSS.Attribute.PADDING});
  523. htmlAttrToCssAttrMap.put(HTML.Attribute.CELLSPACING,
  524. new CSS.Attribute[]{CSS.Attribute.MARGIN});
  525. htmlAttrToCssAttrMap.put(HTML.Attribute.MARGINWIDTH,
  526. new CSS.Attribute[]{CSS.Attribute.MARGIN_LEFT,
  527. CSS.Attribute.MARGIN_RIGHT});
  528. htmlAttrToCssAttrMap.put(HTML.Attribute.MARGINHEIGHT,
  529. new CSS.Attribute[]{CSS.Attribute.MARGIN_TOP,
  530. CSS.Attribute.MARGIN_BOTTOM});
  531. htmlAttrToCssAttrMap.put(HTML.Attribute.HSPACE,
  532. new CSS.Attribute[]{CSS.Attribute.PADDING_LEFT,
  533. CSS.Attribute.PADDING_RIGHT});
  534. htmlAttrToCssAttrMap.put(HTML.Attribute.VSPACE,
  535. new CSS.Attribute[]{CSS.Attribute.PADDING_BOTTOM,
  536. CSS.Attribute.PADDING_TOP});
  537. htmlAttrToCssAttrMap.put(HTML.Attribute.FACE,
  538. new CSS.Attribute[]{CSS.Attribute.FONT_FAMILY});
  539. htmlAttrToCssAttrMap.put(HTML.Attribute.SIZE,
  540. new CSS.Attribute[]{CSS.Attribute.FONT_SIZE});
  541. htmlAttrToCssAttrMap.put(HTML.Attribute.VALIGN,
  542. new CSS.Attribute[]{CSS.Attribute.VERTICAL_ALIGN});
  543. htmlAttrToCssAttrMap.put(HTML.Attribute.ALIGN,
  544. new CSS.Attribute[]{CSS.Attribute.VERTICAL_ALIGN,
  545. CSS.Attribute.TEXT_ALIGN,
  546. CSS.Attribute.FLOAT});
  547. htmlAttrToCssAttrMap.put(HTML.Attribute.TYPE,
  548. new CSS.Attribute[]{CSS.Attribute.LIST_STYLE_TYPE});
  549. // initialize StyleConstants mapping
  550. styleConstantToCssMap.put(StyleConstants.FontFamily,
  551. CSS.Attribute.FONT_FAMILY);
  552. styleConstantToCssMap.put(StyleConstants.FontSize,
  553. CSS.Attribute.FONT_SIZE);
  554. styleConstantToCssMap.put(StyleConstants.Bold,
  555. CSS.Attribute.FONT_WEIGHT);
  556. styleConstantToCssMap.put(StyleConstants.Italic,
  557. CSS.Attribute.FONT_STYLE);
  558. styleConstantToCssMap.put(StyleConstants.Underline,
  559. CSS.Attribute.TEXT_DECORATION);
  560. styleConstantToCssMap.put(StyleConstants.StrikeThrough,
  561. CSS.Attribute.TEXT_DECORATION);
  562. styleConstantToCssMap.put(StyleConstants.Superscript,
  563. CSS.Attribute.VERTICAL_ALIGN);
  564. styleConstantToCssMap.put(StyleConstants.Subscript,
  565. CSS.Attribute.VERTICAL_ALIGN);
  566. styleConstantToCssMap.put(StyleConstants.Foreground,
  567. CSS.Attribute.COLOR);
  568. styleConstantToCssMap.put(StyleConstants.Background,
  569. CSS.Attribute.BACKGROUND_COLOR);
  570. styleConstantToCssMap.put(StyleConstants.FirstLineIndent,
  571. CSS.Attribute.TEXT_INDENT);
  572. styleConstantToCssMap.put(StyleConstants.LeftIndent,
  573. CSS.Attribute.MARGIN_LEFT);
  574. styleConstantToCssMap.put(StyleConstants.RightIndent,
  575. CSS.Attribute.MARGIN_RIGHT);
  576. styleConstantToCssMap.put(StyleConstants.SpaceAbove,
  577. CSS.Attribute.MARGIN_TOP);
  578. styleConstantToCssMap.put(StyleConstants.SpaceBelow,
  579. CSS.Attribute.MARGIN_BOTTOM);
  580. styleConstantToCssMap.put(StyleConstants.Alignment,
  581. CSS.Attribute.TEXT_ALIGN);
  582. // HTML->CSS
  583. htmlValueToCssValueMap.put("disc", CSS.Value.DISC);
  584. htmlValueToCssValueMap.put("square", CSS.Value.SQUARE);
  585. htmlValueToCssValueMap.put("circle", CSS.Value.CIRCLE);
  586. htmlValueToCssValueMap.put("1", CSS.Value.DECIMAL);
  587. htmlValueToCssValueMap.put("a", CSS.Value.LOWER_ALPHA);
  588. htmlValueToCssValueMap.put("A", CSS.Value.UPPER_ALPHA);
  589. htmlValueToCssValueMap.put("i", CSS.Value.LOWER_ROMAN);
  590. htmlValueToCssValueMap.put("I", CSS.Value.UPPER_ROMAN);
  591. // CSS-> internal CSS
  592. cssValueToInternalValueMap.put("disc", CSS.Value.DISC);
  593. cssValueToInternalValueMap.put("square", CSS.Value.SQUARE);
  594. cssValueToInternalValueMap.put("circle", CSS.Value.CIRCLE);
  595. cssValueToInternalValueMap.put("decimal", CSS.Value.DECIMAL);
  596. cssValueToInternalValueMap.put("lower-roman", CSS.Value.LOWER_ROMAN);
  597. cssValueToInternalValueMap.put("upper-roman", CSS.Value.UPPER_ROMAN);
  598. cssValueToInternalValueMap.put("lower-alpha", CSS.Value.LOWER_ALPHA);
  599. cssValueToInternalValueMap.put("upper-alpha", CSS.Value.UPPER_ALPHA);
  600. // Register all the CSS attribute keys for archival/unarchival
  601. Object[] keys = CSS.Attribute.allAttributes;
  602. try {
  603. for (int i = 0; i < keys.length; i++) {
  604. StyleContext.registerStaticAttributeKey(keys[i]);
  605. }
  606. } catch (Throwable e) {
  607. e.printStackTrace();
  608. }
  609. }
  610. /**
  611. * Return the set of all possible CSS attribute keys.
  612. */
  613. public static Attribute[] getAllAttributeKeys() {
  614. Attribute[] keys = new Attribute[Attribute.allAttributes.length];
  615. System.arraycopy(Attribute.allAttributes, 0, keys, 0, Attribute.allAttributes.length);
  616. return keys;
  617. }
  618. /**
  619. * Translate a string to a CSS.Attribute object. This
  620. * will return null if there is no attribute by the given
  621. * name.
  622. * @param name the name of the css attribute to fetch the
  623. * typesafe enumeration for.
  624. * @returns the CSS.Attribute object, or null if the string
  625. * doesn't represent a valid attribute key.
  626. */
  627. public static final Attribute getAttribute(String name) {
  628. return (Attribute) attributeMap.get(name);
  629. }
  630. /**
  631. * Translate a string to a CSS.Value object. This
  632. * will return null if there is no value by the given
  633. * name.
  634. * @param name the name of the css value to fetch the
  635. * typesafe enumeration for.
  636. * @returns the CSS.Value object, or null if the string
  637. * doesn't represent a valid css value name. This does
  638. * not mean it doesn't represent a valid css value.
  639. */
  640. static final Value getValue(String name) {
  641. return (Value) valueMap.get(name);
  642. }
  643. //
  644. // Conversion related methods/classes
  645. //
  646. /**
  647. * Converts a type Color to a hex string
  648. * in the format "#RRGGBB"
  649. */
  650. static String colorToHex(Color color) {
  651. String colorstr = new String("#");
  652. // Red
  653. String str = Integer.toHexString(color.getRed());
  654. if (str.length() > 2)
  655. str = str.substring(0, 2);
  656. else if (str.length() < 2)
  657. colorstr += "0" + str;
  658. else
  659. colorstr += str;
  660. // Green
  661. str = Integer.toHexString(color.getGreen());
  662. if (str.length() > 2)
  663. str = str.substring(0, 2);
  664. else if (str.length() < 2)
  665. colorstr += "0" + str;
  666. else
  667. colorstr += str;
  668. // Blue
  669. str = Integer.toHexString(color.getBlue());
  670. if (str.length() > 2)
  671. str = str.substring(0, 2);
  672. else if (str.length() < 2)
  673. colorstr += "0" + str;
  674. else
  675. colorstr += str;
  676. return colorstr;
  677. }
  678. /**
  679. * Convert a "#FFFFFF" hex string to a Color.
  680. * If the color specification is bad, an attempt
  681. * will be made to fix it up.
  682. */
  683. static final Color hexToColor(String value) {
  684. if (value.startsWith("#")) {
  685. String digits = value.substring(1, Math.min(value.length(), 7));
  686. String hstr = "0x" + digits;
  687. Color c = Color.decode(hstr);
  688. return c;
  689. }
  690. return null;
  691. }
  692. /**
  693. * Convert a color string "RED" or "#NNNNNN" to a Color.
  694. * Note: This will only convert the HTML3.2 colors strings
  695. * or string of length 7
  696. * otherwise, it will return null.
  697. */
  698. static Color stringToColor(String str) {
  699. Color color = null;
  700. if (str.charAt(0) == '#')
  701. color = hexToColor(str);
  702. else if (str.equalsIgnoreCase("Black"))
  703. color = hexToColor("#000000");
  704. else if(str.equalsIgnoreCase("Silver"))
  705. color = hexToColor("#C0C0C0");
  706. else if(str.equalsIgnoreCase("Gray"))
  707. color = hexToColor("#808080");
  708. else if(str.equalsIgnoreCase("White"))
  709. color = hexToColor("#FFFFFF");
  710. else if(str.equalsIgnoreCase("Maroon"))
  711. color = hexToColor("#800000");
  712. else if(str.equalsIgnoreCase("Red"))
  713. color = hexToColor("#FF0000");
  714. else if(str.equalsIgnoreCase("Purple"))
  715. color = hexToColor("#800080");
  716. else if(str.equalsIgnoreCase("Fuchsia"))
  717. color = hexToColor("#FF00FF");
  718. else if(str.equalsIgnoreCase("Green"))
  719. color = hexToColor("#008000");
  720. else if(str.equalsIgnoreCase("Lime"))
  721. color = hexToColor("#00FF00");
  722. else if(str.equalsIgnoreCase("Olive"))
  723. color = hexToColor("#808000");
  724. else if(str.equalsIgnoreCase("Yellow"))
  725. color = hexToColor("#FFFF00");
  726. else if(str.equalsIgnoreCase("Navy"))
  727. color = hexToColor("#000080");
  728. else if(str.equalsIgnoreCase("Blue"))
  729. color = hexToColor("#0000FF");
  730. else if(str.equalsIgnoreCase("Teal"))
  731. color = hexToColor("#008080");
  732. else if(str.equalsIgnoreCase("Aqua"))
  733. color = hexToColor("#00FFFF");
  734. return color;
  735. }
  736. static int getIndexOfSize(float pt) {
  737. for (int i = 0; i < sizeMap.length; i ++ )
  738. if (pt <= sizeMap[i])
  739. return i;
  740. return sizeMap.length - 1;
  741. }
  742. /**
  743. * Return the point size, given a size index.
  744. */
  745. float getPointSize(int index) {
  746. if (index < 0)
  747. return sizeMap[0];
  748. else if (index > sizeMap.length - 1)
  749. return sizeMap[sizeMap.length - 1];
  750. else
  751. return sizeMap[index];
  752. }
  753. private void translateEmbeddedAttributes(AttributeSet htmlAttrSet,
  754. MutableAttributeSet cssAttrSet) {
  755. Enumeration keys = htmlAttrSet.getAttributeNames();
  756. while (keys.hasMoreElements()) {
  757. Object key = keys.nextElement();
  758. if (key instanceof HTML.Tag) {
  759. HTML.Tag tag = (HTML.Tag)key;
  760. Object o = htmlAttrSet.getAttribute(tag);
  761. if (o != null && o instanceof AttributeSet) {
  762. translateAttributes(tag, (AttributeSet)o, cssAttrSet);
  763. }
  764. } else if (key instanceof CSS.Attribute) {
  765. cssAttrSet.addAttribute(key, htmlAttrSet.getAttribute(key));
  766. }
  767. }
  768. }
  769. private void translateAttributes(HTML.Tag tag,
  770. AttributeSet htmlAttrSet,
  771. MutableAttributeSet cssAttrSet) {
  772. Enumeration names = htmlAttrSet.getAttributeNames();
  773. while (names.hasMoreElements()) {
  774. Object name = names.nextElement();
  775. if (name instanceof HTML.Attribute) {
  776. HTML.Attribute key = (HTML.Attribute)name;
  777. /*
  778. * HTML.Attribute.ALIGN needs special processing.
  779. * It can map to to 1 of many(3) possible CSS attributes
  780. * depending on the nature of the tag the attribute is
  781. * part off and depending on the value of the attribute.
  782. */
  783. if (key == HTML.Attribute.ALIGN) {
  784. String htmlAttrValue = (String)htmlAttrSet.getAttribute(HTML.Attribute.ALIGN);
  785. if (htmlAttrValue != null) {
  786. CSS.Attribute cssAttr = getCssAlignAttribute(tag, htmlAttrSet);
  787. if (cssAttr != null) {
  788. Object o = getCssValue(cssAttr, htmlAttrValue);
  789. if (o != null) {
  790. cssAttrSet.addAttribute(cssAttr, o);
  791. }
  792. }
  793. }
  794. } else {
  795. /*
  796. * The html size attribute has a mapping in the CSS world only
  797. * if it is par of a font or base font tag.
  798. */
  799. if (key == HTML.Attribute.SIZE && !isHTMLFontTag(tag)) {
  800. continue;
  801. }
  802. translateAttribute(key, htmlAttrSet, cssAttrSet);
  803. }
  804. } else if (name instanceof CSS.Attribute) {
  805. cssAttrSet.addAttribute(name, htmlAttrSet.getAttribute(name));
  806. }
  807. }
  808. }
  809. private void translateAttribute(HTML.Attribute key,
  810. AttributeSet htmlAttrSet,
  811. MutableAttributeSet cssAttrSet) {
  812. /*
  813. * In the case of all remaining HTML.Attribute's they
  814. * map to 1 or more CCS.Attribute.
  815. */
  816. CSS.Attribute[] cssAttrList = getCssAttribute(key);
  817. String htmlAttrValue = (String)htmlAttrSet.getAttribute(key);
  818. if (cssAttrList == null || htmlAttrValue == null) {
  819. return;
  820. }
  821. for (int i = 0; i < cssAttrList.length; i++) {
  822. Object o = getCssValue(cssAttrList[i], htmlAttrValue);
  823. if (o != null) {
  824. cssAttrSet.addAttribute(cssAttrList[i], o);
  825. }
  826. }
  827. }
  828. /**
  829. * Given a CSS.Attribute object and its corresponding HTML.Attribute's
  830. * value, this method returns a CssValue object to associate with the
  831. * CSS attribute.
  832. *
  833. * @param the CSS.Attribute
  834. * @param a String containing the value associated HTML.Attribtue.
  835. */
  836. Object getCssValue(CSS.Attribute cssAttr, String htmlAttrValue) {
  837. CssValue value = (CssValue)valueConvertor.get(cssAttr);
  838. Object o = value.parseHtmlValue(htmlAttrValue);
  839. return o;
  840. }
  841. /**
  842. * Maps an HTML.Attribute object to its appropriate CSS.Attributes.
  843. *
  844. * @param HTML.Attribute
  845. * @return CSS.Attribute[]
  846. */
  847. private CSS.Attribute[] getCssAttribute(HTML.Attribute hAttr) {
  848. return (CSS.Attribute[])htmlAttrToCssAttrMap.get(hAttr);
  849. }
  850. /**
  851. * Maps HTML.Attribute.ALIGN to either:
  852. * CSS.Attribute.TEXT_ALIGN
  853. * CSS.Attribute.FLOAT
  854. * CSS.Attribute.VERTICAL_ALIGN
  855. * based on the tag associated with the attribute and the
  856. * value of the attribute.
  857. *
  858. * @param AttributeSet containing html attributes.
  859. * @return CSS.Attribute mapping for HTML.Attribute.ALIGN.
  860. */
  861. private CSS.Attribute getCssAlignAttribute(HTML.Tag tag,
  862. AttributeSet htmlAttrSet) {
  863. return CSS.Attribute.TEXT_ALIGN;
  864. /*
  865. String htmlAttrValue = (String)htmlAttrSet.getAttribute(HTML.Attribute.ALIGN);
  866. CSS.Attribute cssAttr = CSS.Attribute.TEXT_ALIGN;
  867. if (htmlAttrValue != null && htmlAttrSet instanceof Element) {
  868. Element elem = (Element)htmlAttrSet;
  869. if (!elem.isLeaf() && tag.isBlock() && validTextAlignValue(htmlAttrValue)) {
  870. return CSS.Attribute.TEXT_ALIGN;
  871. } else if (isFloater(htmlAttrValue)) {
  872. return CSS.Attribute.FLOAT;
  873. } else if (elem.isLeaf()) {
  874. return CSS.Attribute.VERTICAL_ALIGN;
  875. }
  876. }
  877. return null;
  878. */
  879. }
  880. /**
  881. * Fetches the tag associated with the HTML AttributeSet.
  882. *
  883. * @param AttributeSet containing the html attributes.
  884. * @return HTML.Tag
  885. */
  886. private HTML.Tag getHTMLTag(AttributeSet htmlAttrSet) {
  887. Object o = htmlAttrSet.getAttribute(StyleConstants.NameAttribute);
  888. if (o instanceof HTML.Tag) {
  889. HTML.Tag tag = (HTML.Tag) o;
  890. return tag;
  891. }
  892. return null;
  893. }
  894. private boolean isHTMLFontTag(HTML.Tag tag) {
  895. return (tag != null && ((tag == HTML.Tag.FONT) || (tag == HTML.Tag.BASEFONT)));
  896. }
  897. private boolean isFloater(String alignValue) {
  898. return (alignValue.equals("left") || alignValue.equals("right"));
  899. }
  900. private boolean validTextAlignValue(String alignValue) {
  901. return (isFloater(alignValue) || alignValue.equals("center"));
  902. }
  903. /**
  904. * Base class to CSS values in the attribute sets. This
  905. * is intended to act as a convertor to/from other attribute
  906. * formats.
  907. * <p>
  908. * The css parser uses the parseCssValue method to convert
  909. * a string to whatever format is appropriate a given key
  910. * (i.e. these convertors are stored in a map using the
  911. * CSS.Attribute as a key and the CssValue as the value).
  912. * <p>
  913. * The html to css conversion process first converts the
  914. * HTML.Attribute to a CSS.Attribute, and then calls
  915. * the parseHtmlValue method on the value of the html
  916. * attribute to produce the corresponding css value.
  917. * <p>
  918. * The StyleConstants to CSS conversion process first
  919. * converts the StyleConstants attribute to a
  920. * CSS.Attribute, and then calls the fromStyleConstants
  921. * method to convert the StyleConstants value to a
  922. * CSS value.
  923. * <p>
  924. * The CSS to StyleConstants conversion process first
  925. * converts the StyleConstants attribute to a
  926. * CSS.Attribute, and then calls the toStyleConstants
  927. * method to convert the CSS value to a StyleConstants
  928. * value.
  929. */
  930. static class CssValue implements Serializable {
  931. /**
  932. * Convert a css value string to the internal format
  933. * (for fast processing) used in the attribute sets.
  934. * The fallback storage for any value that we don't
  935. * have a special binary format for is a String.
  936. */
  937. Object parseCssValue(String value) {
  938. return value;
  939. }
  940. /**
  941. * Convert an html attribute value to a css attribute
  942. * value. If there is no conversion, return null.
  943. * This is implemented to simply forward to the css
  944. * parsing by default (since some of the attribute
  945. * values are the same). If the attribute value
  946. * isn't recognized as a css value it is generally
  947. * returned as null.
  948. */
  949. Object parseHtmlValue(String value) {
  950. return parseCssValue(value);
  951. }
  952. /**
  953. * Convert a StyleConstants attribute value to
  954. * a css attribute value. If there is no conversion
  955. * return null. By default, there is no conversion.
  956. *
  957. * @param key the StyleConstants attribute.
  958. * @param value the value of a StyleConstants attribute,
  959. * to be converted.
  960. * @returns the CSS value that represents the StyleConstants
  961. * value.
  962. */
  963. Object fromStyleConstants(StyleConstants key, Object value) {
  964. return null;
  965. }
  966. /**
  967. * Convert a CSS attribute value to a StyleConstants
  968. * value. If there is no conversion, return null.
  969. * By default, there is no conversion.
  970. *
  971. * @param key the StyleConstants attribute.
  972. * @returns the StyleConstants attribute value that
  973. * represents the CSS attribute value.
  974. */
  975. Object toStyleConstants(StyleConstants key) {
  976. return null;
  977. }
  978. /**
  979. * Return the css format of the value
  980. */
  981. public String toString() {
  982. return svalue;
  983. }
  984. /**
  985. * The value as a string... before conversion to a
  986. * binary format.
  987. */
  988. String svalue;
  989. }
  990. /**
  991. * By default CSS attributes are represented as simple
  992. * strings. They also have no conversion to/from
  993. * StyleConstants by default. This class represents the
  994. * value as a string (via the superclass), but
  995. * provides StyleConstants conversion support for the
  996. * CSS attributes that are held as strings.
  997. */
  998. static class StringValue extends CssValue {
  999. /**
  1000. * Convert a css value string to the internal format
  1001. * (for fast processing) used in the attribute sets.
  1002. * This produces a StringValue, so that it can be
  1003. * used to convert from CSS to StyleConstants values.
  1004. */
  1005. Object parseCssValue(String value) {
  1006. StringValue sv = new StringValue();
  1007. sv.svalue = value;
  1008. return sv;
  1009. }
  1010. /**
  1011. * Convert a StyleConstants attribute value to
  1012. * a css attribute value. If there is no conversion
  1013. * return null.
  1014. *
  1015. * @param key the StyleConstants attribute.
  1016. * @param value the value of a StyleConstants attribute,
  1017. * to be converted.
  1018. * @returns the CSS value that represents the StyleConstants
  1019. * value.
  1020. */
  1021. Object fromStyleConstants(StyleConstants key, Object value) {
  1022. if (key == StyleConstants.Italic) {
  1023. if (value.equals(Boolean.TRUE)) {
  1024. return parseCssValue("italic");
  1025. }
  1026. return parseCssValue("");
  1027. } else if (key == StyleConstants.Underline) {
  1028. if (value.equals(Boolean.TRUE)) {
  1029. return parseCssValue("underline");
  1030. }
  1031. return parseCssValue("");
  1032. } else if (key == StyleConstants.Alignment) {
  1033. int align = ((Integer)value).intValue();
  1034. String ta;
  1035. switch(align) {
  1036. case StyleConstants.ALIGN_LEFT:
  1037. ta = "left";
  1038. break;
  1039. case StyleConstants.ALIGN_RIGHT:
  1040. ta = "right";
  1041. break;
  1042. case StyleConstants.ALIGN_CENTER:
  1043. ta = "center";
  1044. break;
  1045. case StyleConstants.ALIGN_JUSTIFIED:
  1046. ta = "justify";
  1047. break;
  1048. default:
  1049. ta = "left";
  1050. }
  1051. return parseCssValue(ta);
  1052. } else if (key == StyleConstants.StrikeThrough) {
  1053. if (value.equals(Boolean.TRUE)) {
  1054. return parseCssValue("line-through");
  1055. }
  1056. return parseCssValue("");
  1057. } else if (key == StyleConstants.Superscript) {
  1058. if (value.equals(Boolean.TRUE)) {
  1059. return parseCssValue("super");
  1060. }
  1061. return parseCssValue("");
  1062. } else if (key == StyleConstants.Subscript) {
  1063. if (value.equals(Boolean.TRUE)) {
  1064. return parseCssValue("sub");
  1065. }
  1066. return parseCssValue("");
  1067. }
  1068. return null;
  1069. }
  1070. /**
  1071. * Convert a CSS attribute value to a StyleConstants
  1072. * value. If there is no conversion, return null.
  1073. * By default, there is no conversion.
  1074. *
  1075. * @param key the StyleConstants attribute.
  1076. * @returns the StyleConstants attribute value that
  1077. * represents the CSS attribute value.
  1078. */
  1079. Object toStyleConstants(StyleConstants key) {
  1080. if (key == StyleConstants.Italic) {
  1081. if (svalue.indexOf("italic") >= 0) {
  1082. return Boolean.TRUE;
  1083. }
  1084. return Boolean.FALSE;
  1085. } else if (key == StyleConstants.Underline) {
  1086. if (svalue.indexOf("underline") >= 0) {
  1087. return Boolean.TRUE;
  1088. }
  1089. return Boolean.FALSE;
  1090. } else if (key == StyleConstants.Alignment) {
  1091. if (svalue.equals("right")) {
  1092. return new Integer(StyleConstants.ALIGN_RIGHT);
  1093. } else if (svalue.equals("center")) {
  1094. return new Integer(StyleConstants.ALIGN_CENTER);
  1095. } else if (svalue.equals("justify")) {
  1096. return new Integer(StyleConstants.ALIGN_JUSTIFIED);
  1097. }
  1098. return new Integer(StyleConstants.ALIGN_LEFT);
  1099. } else if (key == StyleConstants.StrikeThrough) {
  1100. if (svalue.indexOf("line-through") >= 0) {
  1101. return Boolean.TRUE;
  1102. }
  1103. return Boolean.FALSE;
  1104. } else if (key == StyleConstants.Superscript) {
  1105. if (svalue.indexOf("super") >= 0) {
  1106. return Boolean.TRUE;
  1107. }
  1108. return Boolean.FALSE;
  1109. } else if (key == StyleConstants.Subscript) {
  1110. if (svalue.indexOf("sub") >= 0) {
  1111. return Boolean.TRUE;
  1112. }
  1113. return Boolean.FALSE;
  1114. }
  1115. return null;
  1116. }
  1117. }
  1118. /**
  1119. * Represents a value for the CSS.FONT_SIZE attribute.
  1120. * The binary format of the value can be one of several
  1121. * types. If the type is Float,
  1122. * the value is specified in terms of point or
  1123. * percentage, depending upon the ending of the
  1124. * associated string.
  1125. * If the type is Integer, the value is specified
  1126. * in terms of a size index.
  1127. */
  1128. class FontSize extends CssValue {
  1129. /**
  1130. * Returns the size in points. This is ultimately
  1131. * what we need for the purpose of creating/fetching
  1132. * a Font object.
  1133. *
  1134. * @param a the attribute set the value is being
  1135. * requested from. We may need to walk up the
  1136. * resolve hierarchy if it's relative.
  1137. */
  1138. float getValue(AttributeSet a) {
  1139. // PENDING(prinz) need to add support for relative
  1140. // and percentage.
  1141. if (index) {
  1142. // it's an index, translate from size table
  1143. return getPointSize((int) value);
  1144. } else {
  1145. return value;
  1146. }
  1147. }
  1148. boolean isRelative() {
  1149. return relative;
  1150. }
  1151. Object parseCssValue(String value) {
  1152. FontSize fs = new FontSize();
  1153. fs.svalue = value;
  1154. try {
  1155. if (value.equals("xx-small")) {
  1156. fs.value = 0;
  1157. fs.index = true;
  1158. } else if (value.equals("x-small")) {
  1159. fs.value = 1;
  1160. fs.index = true;
  1161. } else if (value.equals("small")) {
  1162. fs.value = 2;
  1163. fs.index = true;
  1164. } else if (value.equals("medium")) {
  1165. fs.value = 3;
  1166. fs.index = true;
  1167. } else if (value.equals("large")) {
  1168. fs.value = 4;
  1169. fs.index = true;
  1170. } else if (value.equals("x-large")) {
  1171. fs.value = 5;
  1172. fs.index = true;
  1173. } else if (value.equals("xx-large")) {
  1174. fs.value = 6;
  1175. fs.index = true;
  1176. } else if (value.equals("bigger")) {
  1177. fs.value = 1;
  1178. fs.index = true;
  1179. fs.relative = true;
  1180. } else if (value.equals("smaller")) {
  1181. fs.value = -1;
  1182. fs.index = true;
  1183. fs.relative = true;
  1184. } else if (value.endsWith("pt")) {
  1185. String sz = value.substring(0, value.length() - 2);
  1186. fs.value = Float.valueOf(sz).floatValue();
  1187. } else {
  1188. // TBD - further processing
  1189. fs.value = Float.valueOf(value).floatValue();
  1190. }
  1191. } catch (NumberFormatException nfe) {
  1192. fs = null;
  1193. }
  1194. return fs;
  1195. }
  1196. Object parseHtmlValue(String value) {
  1197. FontSize fs = new FontSize();
  1198. fs.svalue = value;
  1199. try {
  1200. /*
  1201. * relative sizes in the size attribute are relative
  1202. * to the <basefont>'s size.
  1203. */
  1204. int baseFontSize = getBaseFontSize();
  1205. if ((value != null) && (value.charAt(0) == '+')) {
  1206. int relSize = Integer.valueOf(value.substring(1)).intValue();
  1207. fs.value = baseFontSize + relSize;
  1208. fs.index = true;
  1209. } else if ((value != null) && (value.charAt(0) == '-')) {
  1210. int relSize = -Integer.valueOf(value.substring(1)).intValue();
  1211. fs.value = baseFontSize + relSize;
  1212. fs.index = true;
  1213. } else {
  1214. fs.value = Integer.parseInt(value);
  1215. if (fs.value > 6) {
  1216. fs.value = 6;
  1217. } else if (fs.value < 0) {
  1218. fs.value = 0;
  1219. }
  1220. fs.index = true;
  1221. }
  1222. } catch (NumberFormatException nfe) {
  1223. fs = null;
  1224. }
  1225. return fs;
  1226. }
  1227. /**
  1228. * Convert a StyleConstants attribute value to
  1229. * a css attribute value. If there is no conversion
  1230. * return null. By default, there is no conversion.
  1231. *
  1232. * @param key the StyleConstants attribute.
  1233. * @param value the value of a StyleConstants attribute,
  1234. * to be converted.
  1235. * @returns the CSS value that represents the StyleConstants
  1236. * value.
  1237. */
  1238. Object fromStyleConstants(StyleConstants key, Object value) {
  1239. return parseCssValue(value.toString());
  1240. }
  1241. /**
  1242. * Convert a CSS attribute value to a StyleConstants
  1243. * value. If there is no conversion, return null.
  1244. * By default, there is no conversion.
  1245. *
  1246. * @param key the StyleConstants attribute.
  1247. * @returns the StyleConstants attribute value that
  1248. * represents the CSS attribute value.
  1249. */
  1250. Object toStyleConstants(StyleConstants key) {
  1251. return new Integer((int) getValue(null));
  1252. }
  1253. float value;
  1254. boolean relative;
  1255. boolean index;
  1256. boolean percentage;
  1257. }
  1258. static class FontFamily extends CssValue {
  1259. /**
  1260. * Returns the font family to use. This is expected
  1261. * to be a legal font for this platform.
  1262. */
  1263. String getValue() {
  1264. return family;
  1265. }
  1266. Object parseCssValue(String value) {
  1267. FontFamily ff = new FontFamily();
  1268. // TBD - a real implementation
  1269. if (value.equals("monospace")) {
  1270. ff.family = "Monospaced";
  1271. }
  1272. else {
  1273. ff.family = value;
  1274. }
  1275. ff.svalue = value;
  1276. return ff;
  1277. }
  1278. Object parseHtmlValue(String value) {
  1279. // TBD
  1280. return parseCssValue(value);
  1281. }
  1282. /**
  1283. * Convert a StyleConstants attribute value to
  1284. * a css attribute value. If there is no conversion
  1285. * return null. By default, there is no conversion.
  1286. *
  1287. * @param key the StyleConstants attribute.
  1288. * @param value the value of a StyleConstants attribute,
  1289. * to be converted.
  1290. * @returns the CSS value that represents the StyleConstants
  1291. * value.
  1292. */
  1293. Object fromStyleConstants(StyleConstants key, Object value) {
  1294. return parseCssValue(value.toString());
  1295. }
  1296. /**
  1297. * Convert a CSS attribute value to a StyleConstants
  1298. * value. If there is no conversion, return null.
  1299. * By default, there is no conversion.
  1300. *
  1301. * @param key the StyleConstants attribute.
  1302. * @returns the StyleConstants attribute value that
  1303. * represents the CSS attribute value.
  1304. */
  1305. Object toStyleConstants(StyleConstants key) {
  1306. return family;
  1307. }
  1308. String family;
  1309. }
  1310. static class FontWeight extends CssValue {
  1311. int getValue() {
  1312. return weight;
  1313. }
  1314. Object parseCssValue(String value) {
  1315. FontWeight fw = new FontWeight();
  1316. fw.svalue = value;
  1317. if (value.equals("bold")) {
  1318. fw.weight = 700;
  1319. } else if (value.equals("normal")) {
  1320. fw.weight = 400;
  1321. } else {
  1322. // PENDING(prinz) add support for relative values
  1323. try {
  1324. fw.weight = Integer.parseInt(value);
  1325. } catch (NumberFormatException nfe) {
  1326. fw = null;
  1327. }
  1328. }
  1329. return fw;
  1330. }
  1331. /**
  1332. * Convert a StyleConstants attribute value to
  1333. * a css attribute value. If there is no conversion
  1334. * return null. By default, there is no conversion.
  1335. *
  1336. * @param key the StyleConstants attribute.
  1337. * @param value the value of a StyleConstants attribute,
  1338. * to be converted.
  1339. * @returns the CSS value that represents the StyleConstants
  1340. * value.
  1341. */
  1342. Object fromStyleConstants(StyleConstants key, Object value) {
  1343. if (value.equals(Boolean.TRUE)) {
  1344. return parseCssValue("bold");
  1345. }
  1346. return parseCssValue("normal");
  1347. }
  1348. /**
  1349. * Convert a CSS attribute value to a StyleConstants
  1350. * value. If there is no conversion, return null.
  1351. * By default, there is no conversion.
  1352. *
  1353. * @param key the StyleConstants attribute.
  1354. * @returns the StyleConstants attribute value that
  1355. * represents the CSS attribute value.
  1356. */
  1357. Object toStyleConstants(StyleConstants key) {
  1358. return (weight > 500) ? Boolean.TRUE : Boolean.FALSE;
  1359. }
  1360. int weight;
  1361. }
  1362. static class ColorValue extends CssValue {
  1363. /**
  1364. * Returns the color to use.
  1365. */
  1366. Color getValue() {
  1367. return c;
  1368. }
  1369. Object parseCssValue(String value) {
  1370. Color c = stringToColor(value);
  1371. if (c != null) {
  1372. ColorValue cv = new ColorValue();
  1373. cv.svalue = value;
  1374. cv.c = c;
  1375. return cv;
  1376. }
  1377. return null;
  1378. }
  1379. Object parseHtmlValue(String value) {
  1380. return parseCssValue(value);
  1381. }
  1382. /**
  1383. * Convert a StyleConstants attribute value to
  1384. * a css attribute value. If there is no conversion
  1385. * return null. By default, there is no conversion.
  1386. *
  1387. * @param key the StyleConstants attribute.
  1388. * @param value the value of a StyleConstants attribute,
  1389. * to be converted.
  1390. * @returns the CSS value that represents the StyleConstants
  1391. * value.
  1392. */
  1393. Object fromStyleConstants(StyleConstants key, Object value) {
  1394. return parseCssValue(colorToHex((Color) value));
  1395. }
  1396. /**
  1397. * Convert a CSS attribute value to a StyleConstants
  1398. * value. If there is no conversion, return null.
  1399. * By default, there is no conversion.
  1400. *
  1401. * @param key the StyleConstants attribute.
  1402. * @returns the StyleConstants attribute value that
  1403. * represents the CSS attribute value.
  1404. */
  1405. Object toStyleConstants(StyleConstants key) {
  1406. return c;
  1407. }
  1408. Color c;
  1409. }
  1410. static class BorderStyle extends CssValue {
  1411. CSS.Value getValue() {
  1412. return style;
  1413. }
  1414. Object parseCssValue(String value) {
  1415. CSS.Value cssv = CSS.getValue(value);
  1416. if (cssv != null) {
  1417. if ((cssv == CSS.Value.INSET) ||
  1418. (cssv == CSS.Value.OUTSET) ||
  1419. (cssv == CSS.Value.NONE) ||
  1420. (cssv == CSS.Value.DOTTED) ||
  1421. (cssv == CSS.Value.DASHED) ||
  1422. (cssv == CSS.Value.SOLID) ||
  1423. (cssv == CSS.Value.DOUBLE) ||
  1424. (cssv == CSS.Value.GROOVE) ||
  1425. (cssv == CSS.Value.RIDGE)) {
  1426. BorderStyle bs = new BorderStyle();
  1427. bs.svalue = value;
  1428. bs.style = cssv;
  1429. return bs;
  1430. }
  1431. }
  1432. return null;
  1433. }
  1434. private void writeObject(java.io.ObjectOutputStream s)
  1435. throws IOException {
  1436. s.defaultWriteObject();
  1437. if (style == null) {
  1438. s.writeObject(null);
  1439. }
  1440. else {
  1441. s.writeObject(style.toString());
  1442. }
  1443. }
  1444. private void readObject(ObjectInputStream s)
  1445. throws ClassNotFoundException, IOException {
  1446. s.defaultReadObject();
  1447. Object value = s.readObject();
  1448. if (value != null) {
  1449. style = CSS.getValue((String)value);
  1450. }
  1451. }
  1452. // CSS.Values are static, don't archive it.
  1453. transient private CSS.Value style;
  1454. }
  1455. static class LengthValue extends CssValue {
  1456. /**
  1457. * Returns the length (span) to use.
  1458. */
  1459. float getValue() {
  1460. return span;
  1461. }
  1462. Object parseCssValue(String value) {
  1463. LengthValue lv = new LengthValue();
  1464. lv.svalue = value;
  1465. try {
  1466. if (value.endsWith("pt")) {
  1467. String sz = value.substring(0, value.length() - 2);
  1468. lv.span = Float.valueOf(sz).floatValue();
  1469. } else {
  1470. // TBD - further processing
  1471. lv.span = Float.valueOf(value).floatValue();
  1472. }
  1473. } catch (NumberFormatException nfe) {
  1474. lv = null;
  1475. }
  1476. return lv;
  1477. }
  1478. Object parseHtmlValue(String value) {
  1479. if (value.equals(HTML.NULL_ATTRIBUTE_VALUE)) {
  1480. value = "1";
  1481. }
  1482. return parseCssValue(value);
  1483. }
  1484. /**
  1485. * Convert a StyleConstants attribute value to
  1486. * a css attribute value. If there is no conversion
  1487. * return null. By default, there is no conversion.
  1488. *
  1489. * @param key the StyleConstants attribute.
  1490. * @param value the value of a StyleConstants attribute,
  1491. * to be converted.
  1492. * @returns the CSS value that represents the StyleConstants
  1493. * value.
  1494. */
  1495. Object fromStyleConstants(StyleConstants key, Object value) {
  1496. LengthValue v = new LengthValue();
  1497. v.svalue = value.toString();
  1498. v.span = ((Float)value).floatValue();
  1499. return v;
  1500. }
  1501. /**
  1502. * Convert a CSS attribute value to a StyleConstants
  1503. * value. If there is no conversion, return null.
  1504. * By default, there is no conversion.
  1505. *
  1506. * @param key the StyleConstants attribute.
  1507. * @returns the StyleConstants attribute value that
  1508. * represents the CSS attribute value.
  1509. */
  1510. Object toStyleConstants(StyleConstants key) {
  1511. return new Float(span);
  1512. }
  1513. float span;
  1514. }
  1515. /**
  1516. * Handles conversion of list types.
  1517. */
  1518. static class ListType extends CssValue {
  1519. Object parseCssValue(String value) {
  1520. Object retValue = cssValueToInternalValueMap.get(value);
  1521. if (retValue == null) {
  1522. retValue = cssValueToInternalValueMap.get(value.toLowerCase());
  1523. }
  1524. return retValue;
  1525. }
  1526. Object parseHtmlValue(String value) {
  1527. Object retValue = htmlValueToCssValueMap.get(value);
  1528. if (retValue == null) {
  1529. retValue = htmlValueToCssValueMap.get(value.toLowerCase());
  1530. }
  1531. return retValue;
  1532. }
  1533. }
  1534. //
  1535. // Serialization support
  1536. //
  1537. private void writeObject(java.io.ObjectOutputStream s)
  1538. throws IOException
  1539. {
  1540. s.defaultWriteObject();
  1541. // Determine what values in valueConvertor need to be written out.
  1542. Enumeration keys = valueConvertor.keys();
  1543. s.writeInt(valueConvertor.size());
  1544. if (keys != null) {
  1545. while (keys.hasMoreElements()) {
  1546. Object key = keys.nextElement();
  1547. Object value = valueConvertor.get(key);
  1548. if (!(key instanceof Serializable) &&
  1549. (key = StyleContext.getStaticAttributeKey(key)) == null) {
  1550. // Should we throw an exception here?
  1551. key = null;
  1552. value = null;
  1553. }
  1554. else if (!(value instanceof Serializable) &&
  1555. (value = StyleContext.getStaticAttributeKey(value)) == null){
  1556. // Should we throw an exception here?
  1557. key = null;
  1558. value = null;
  1559. }
  1560. s.writeObject(key);
  1561. s.writeObject(value);
  1562. }
  1563. }
  1564. }
  1565. private void readObject(ObjectInputStream s)
  1566. throws ClassNotFoundException, IOException
  1567. {
  1568. s.defaultReadObject();
  1569. // Reconstruct the hashtable.
  1570. int numValues = s.readInt();
  1571. valueConvertor = new Hashtable(Math.max(1, numValues));
  1572. while (numValues-- > 0) {
  1573. Object key = s.readObject();
  1574. Object value = s.readObject();
  1575. Object staticKey = StyleContext.getStaticAttribute(key);
  1576. if (staticKey != null) {
  1577. key = staticKey;
  1578. }
  1579. Object staticValue = StyleContext.getStaticAttribute(value);
  1580. if (staticValue != null) {
  1581. value = staticValue;
  1582. }
  1583. if (key != null && value != null) {
  1584. valueConvertor.put(key, value);
  1585. }
  1586. }
  1587. }
  1588. //
  1589. // Instance variables
  1590. //
  1591. /** Maps from CSS key to CssValue. */
  1592. private transient Hashtable valueConvertor;
  1593. /** Size used for relative units. */
  1594. private int baseFontSize;
  1595. }