001/* CSS.java -- Provides CSS attributes
002   Copyright (C) 2005 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.swing.text.html;
039
040import gnu.javax.swing.text.html.css.BorderStyle;
041import gnu.javax.swing.text.html.css.BorderWidth;
042import gnu.javax.swing.text.html.css.CSSColor;
043import gnu.javax.swing.text.html.css.FontSize;
044import gnu.javax.swing.text.html.css.FontStyle;
045import gnu.javax.swing.text.html.css.FontWeight;
046import gnu.javax.swing.text.html.css.Length;
047
048import java.io.Serializable;
049import java.util.HashMap;
050import java.util.StringTokenizer;
051
052import javax.swing.text.MutableAttributeSet;
053
054/**
055 * Provides CSS attributes to be used by the HTML view classes. The constants
056 * defined here are used as keys for text attributes for use in
057 * {@link javax.swing.text.AttributeSet}s of {@link javax.swing.text.Element}s.
058 *
059 * @author Roman Kennke (kennke@aicas.com)
060 */
061public class CSS implements Serializable
062{
063  /**
064   * Returns an array of all CSS attributes.
065   *
066   * @return All available CSS.Attribute objects.
067   */
068  public static CSS.Attribute[] getAllAttributeKeys()
069  {
070    Object[] src = Attribute.attributeMap.values().toArray();
071    CSS.Attribute[] dst = new CSS.Attribute[ src.length ];
072    System.arraycopy(src, 0, dst, 0, src.length);
073    return dst;
074  }
075
076  /**
077   * Returns an a given CSS attribute.
078   *
079   * @param name - The name of the attribute.
080   * @return The CSS attribute with the given name, or <code>null</code> if
081   * no attribute with that name exists.
082   */
083  public static CSS.Attribute getAttribute(String name)
084  {
085    return (CSS.Attribute)Attribute.attributeMap.get( name );
086  }
087
088  public static final class Attribute
089  {
090    /**
091     * The CSS attribute 'background'.
092     */
093    public static final Attribute BACKGROUND =
094      new Attribute("background", false, null);
095
096    /**
097     * The CSS attribute 'background-attachment'.
098     */
099    public static final Attribute BACKGROUND_ATTACHMENT =
100      new Attribute("background-attachment", false, "scroll");
101
102    /**
103     * The CSS attribute 'background-color'.
104     */
105    public static final Attribute BACKGROUND_COLOR =
106      new Attribute("background-color", false, "transparent");
107
108    /**
109     * The CSS attribute 'background-image'.
110     */
111    public static final Attribute BACKGROUND_IMAGE =
112      new Attribute("background-image", false, "none");
113
114    /**
115     * The CSS attribute 'background-position'.
116     */
117    public static final Attribute BACKGROUND_POSITION =
118      new Attribute("background-position", false, null);
119
120    /**
121     * The CSS attribute 'background-repeat'.
122     */
123    public static final Attribute BACKGROUND_REPEAT =
124      new Attribute("background-repeat", false, "repeat");
125
126    /**
127     * The CSS attribute 'border'.
128     */
129    public static final Attribute BORDER = new Attribute("border", false, null);
130
131    /**
132     * The CSS attribute 'border-bottom'.
133     */
134    public static final Attribute BORDER_BOTTOM =
135      new Attribute("border-bottom", false, null);
136
137    /**
138     * The CSS attribute 'border-bottom-width'.
139     */
140    public static final Attribute BORDER_BOTTOM_WIDTH =
141      new Attribute("border-bottom-width", false, "medium");
142
143    /**
144     * The CSS attribute 'border-color'.
145     */
146    public static final Attribute BORDER_COLOR =
147      new Attribute("border-color", false, "black");
148
149    /**
150     * The CSS attribute 'border-left'.
151     */
152    public static final Attribute BORDER_LEFT =
153      new Attribute("border-left", false, null);
154
155    /**
156     * The CSS attribute 'border-left-width'.
157     */
158    public static final Attribute BORDER_LEFT_WIDTH =
159      new Attribute("border-left-width", false, "medium");
160
161    /**
162     * The CSS attribute 'border-right'.
163     */
164    public static final Attribute BORDER_RIGHT =
165      new Attribute("border-right", false, null);
166
167    /**
168     * The CSS attribute 'border-right-width'.
169     */
170    public static final Attribute BORDER_RIGHT_WIDTH =
171      new Attribute("border-right-width", false, "medium");
172
173    /**
174     * The CSS attribute 'border-style'.
175     */
176    public static final Attribute BORDER_STYLE =
177      new Attribute("border-style", false, "none");
178
179    /**
180     * The CSS attribute 'border-top'.
181     */
182    public static final Attribute BORDER_TOP =
183      new Attribute("border-top", false, null);
184
185    /**
186     * The CSS attribute 'border-top-width'.
187     */
188    public static final Attribute BORDER_TOP_WIDTH =
189      new Attribute("border-top-width", false, "medium");
190
191    /**
192     * The CSS attribute 'border-width'.
193     */
194    public static final Attribute BORDER_WIDTH =
195      new Attribute("border-width", false, "medium");
196
197    /**
198     * The CSS attribute 'clear'.
199     */
200    public static final Attribute CLEAR = new Attribute("clear", false, "none");
201
202    /**
203     * The CSS attribute 'color'.
204     */
205    public static final Attribute COLOR = new Attribute("color", true, "black");
206
207    /**
208     * The CSS attribute 'display'.
209     */
210    public static final Attribute DISPLAY =
211      new Attribute("display", false, "block");
212
213    /**
214     * The CSS attribute 'float'.
215     */
216    public static final Attribute FLOAT = new Attribute("float", false, "none");
217
218    /**
219     * The CSS attribute 'font'.
220     */
221    public static final Attribute FONT = new Attribute("font", true, null);
222
223    /**
224     * The CSS attribute 'font-family'.
225     */
226    public static final Attribute FONT_FAMILY =
227      new Attribute("font-family", true, null);
228
229    /**
230     * The CSS attribute 'font-size'.
231     */
232    public static final Attribute FONT_SIZE =
233      new Attribute("font-size", true, "medium");
234
235    /**
236     * The CSS attribute 'font-style'.
237     */
238    public static final Attribute FONT_STYLE =
239      new Attribute("font-style", true, "normal");
240
241    /**
242     * The CSS attribute 'font-variant'.
243     */
244    public static final Attribute FONT_VARIANT =
245      new Attribute("font-variant", true, "normal");
246
247    /**
248     * The CSS attribute 'font-weight'.
249     */
250    public static final Attribute FONT_WEIGHT =
251      new Attribute("font-weight", true, "normal");
252
253    /**
254     * The CSS attribute 'height'.
255     */
256    public static final Attribute HEIGHT =
257      new Attribute("height", false, "auto");
258
259    /**
260     * The CSS attribute 'letter-spacing'.
261     */
262    public static final Attribute LETTER_SPACING =
263      new Attribute("letter-spacing", true, "normal");
264
265    /**
266     * The CSS attribute 'line-height'.
267     */
268    public static final Attribute LINE_HEIGHT =
269      new Attribute("line-height", true, "normal");
270
271    /**
272     * The CSS attribute 'list-style'.
273     */
274    public static final Attribute LIST_STYLE =
275      new Attribute("list-style", true, null);
276
277    /**
278     * The CSS attribute 'list-style-image'.
279     */
280    public static final Attribute LIST_STYLE_IMAGE =
281      new Attribute("list-style-image", true, "none");
282
283    /**
284     * The CSS attribute 'list-style-position'.
285     */
286    public static final Attribute LIST_STYLE_POSITION =
287      new Attribute("list-style-position", true, "outside");
288
289    /**
290     * The CSS attribute 'list-style-type'.
291     */
292    public static final Attribute LIST_STYLE_TYPE =
293      new Attribute("list-style-type", true, "disc");
294
295    /**
296     * The CSS attribute 'margin'.
297     */
298    public static final Attribute MARGIN = new Attribute("margin", false, null);
299
300    /**
301     * The CSS attribute 'margin-bottom'.
302     */
303    public static final Attribute MARGIN_BOTTOM =
304      new Attribute("margin-bottom", false, "0");
305
306    /**
307     * The CSS attribute 'margin-left'.
308     */
309    public static final Attribute MARGIN_LEFT =
310      new Attribute("margin-left", false, "0");
311
312    /**
313     * The CSS attribute 'margin-right'.
314     */
315    public static final Attribute MARGIN_RIGHT =
316      new Attribute("margin-right", false, "0");
317
318    /**
319     * The CSS attribute 'margin-top'.
320     */
321    public static final Attribute MARGIN_TOP =
322      new Attribute("margin-top", false, "0");
323
324    /**
325     * The CSS attribute 'padding'.
326     */
327    public static final Attribute PADDING =
328      new Attribute("padding", false, null);
329
330    /**
331     * The CSS attribute 'padding-bottom'.
332     */
333    public static final Attribute PADDING_BOTTOM =
334      new Attribute("padding-bottom", false, "0");
335
336    /**
337     * The CSS attribute 'padding-left'.
338     */
339    public static final Attribute PADDING_LEFT =
340      new Attribute("padding-left", false, "0");
341
342    /**
343     * The CSS attribute 'padding-right'.
344     */
345    public static final Attribute PADDING_RIGHT =
346      new Attribute("padding-right", false, "0");
347
348    /**
349     * The CSS attribute 'padding-top'.
350     */
351    public static final Attribute PADDING_TOP =
352      new Attribute("padding-top", false, "0");
353
354    /**
355     * The CSS attribute 'text-align'.
356     */
357    public static final Attribute TEXT_ALIGN =
358      new Attribute("text-align", true, null);
359
360    /**
361     * The CSS attribute 'text-decoration'.
362     */
363    public static final Attribute TEXT_DECORATION =
364      new Attribute("text-decoration", true, "none");
365
366    /**
367     * The CSS attribute 'text-indent'.
368     */
369    public static final Attribute TEXT_INDENT =
370      new Attribute("text-indent", true, "0");
371
372    /**
373     * The CSS attribute 'text-transform'.
374     */
375    public static final Attribute TEXT_TRANSFORM =
376      new Attribute("text-transform", true, "none");
377
378    /**
379     * The CSS attribute 'vertical-align'.
380     */
381    public static final Attribute VERTICAL_ALIGN =
382      new Attribute("vertical-align", false, "baseline");
383
384    /**
385     * The CSS attribute 'white-space'.
386     */
387    public static final Attribute WHITE_SPACE =
388      new Attribute("white-space", true, "normal");
389
390    /**
391     * The CSS attribute 'width'.
392     */
393    public static final Attribute WIDTH =
394      new Attribute("width", false, "auto");
395
396    /**
397     * The CSS attribute 'word-spacing'.
398     */
399    public static final Attribute WORD_SPACING =
400      new Attribute("word-spacing", true, "normal");
401
402    // Some GNU Classpath specific extensions.
403    static final Attribute BORDER_TOP_STYLE =
404      new Attribute("border-top-style", false, null);
405    static final Attribute BORDER_BOTTOM_STYLE =
406      new Attribute("border-bottom-style", false, null);
407    static final Attribute BORDER_LEFT_STYLE =
408      new Attribute("border-left-style", false, null);
409    static final Attribute BORDER_RIGHT_STYLE =
410      new Attribute("border-right-style", false, null);
411    static final Attribute BORDER_TOP_COLOR =
412      new Attribute("border-top-color", false, null);
413    static final Attribute BORDER_BOTTOM_COLOR =
414      new Attribute("border-bottom-color", false, null);
415    static final Attribute BORDER_LEFT_COLOR =
416      new Attribute("border-left-color", false, null);
417    static final Attribute BORDER_RIGHT_COLOR =
418      new Attribute("border-right-color", false, null);
419    static final Attribute BORDER_SPACING =
420      new Attribute("border-spacing", false, null);
421    static final Attribute POSITION =
422      new Attribute("position", false, null);
423    static final Attribute LEFT =
424      new Attribute("left", false, null);
425    static final Attribute RIGHT =
426      new Attribute("right", false, null);
427    static final Attribute TOP =
428      new Attribute("top", false, null);
429    static final Attribute BOTTOM =
430      new Attribute("bottom", false, null);
431
432    /**
433     * The attribute string.
434     */
435    String attStr;
436
437    /**
438     * Indicates if this attribute should be inherited from it's parent or
439     * not.
440     */
441    boolean isInherited;
442
443    /**
444     * A default value for this attribute if one exists, otherwise null.
445     */
446    String defaultValue;
447
448    /**
449     * A HashMap of all attributes.
450     */
451    static HashMap attributeMap;
452
453    /**
454     * Creates a new Attribute instance with the specified values.
455     *
456     * @param attr the attribute string
457     * @param inherited if the attribute should be inherited or not
458     * @param def a default value; may be <code>null</code>
459     */
460    Attribute(String attr, boolean inherited, String def)
461    {
462      attStr = attr;
463      isInherited = inherited;
464      defaultValue = def;
465      if( attributeMap == null)
466        attributeMap = new HashMap();
467      attributeMap.put( attr, this );
468    }
469
470    /**
471     * Returns the string representation of this attribute as specified
472     * in the CSS specification.
473     */
474    public String toString()
475    {
476      return attStr;
477    }
478
479    /**
480     * Returns <code>true</code> if the attribute should be inherited from
481     * the parent, <code>false</code> otherwise.
482     *
483     * @return <code>true</code> if the attribute should be inherited from
484     *         the parent, <code>false</code> otherwise
485     */
486    public boolean isInherited()
487    {
488      return isInherited;
489    }
490
491    /**
492     * Returns the default value of this attribute if one exists,
493     * <code>null</code> otherwise.
494     *
495     * @return the default value of this attribute if one exists,
496     *         <code>null</code> otherwise
497     */
498    public String getDefaultValue()
499    {
500      return defaultValue;
501    }
502  }
503
504  /**
505   * Maps attribute values (String) to some converter class, based on the
506   * key.
507   *
508   * @param att the key
509   * @param v the value
510   *
511   * @return the wrapped value
512   */
513  static Object getValue(Attribute att, String v)
514  {
515    Object o;
516    if (att == Attribute.FONT_SIZE)
517      o = new FontSize(v);
518    else if (att == Attribute.FONT_WEIGHT)
519      o = new FontWeight(v);
520    else if (att == Attribute.FONT_STYLE)
521      o = new FontStyle(v);
522    else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR
523             || att == Attribute.BORDER_COLOR
524             || att == Attribute.BORDER_TOP_COLOR
525             || att == Attribute.BORDER_BOTTOM_COLOR
526             || att == Attribute.BORDER_LEFT_COLOR
527             || att == Attribute.BORDER_RIGHT_COLOR)
528      o = new CSSColor(v);
529    else if (att == Attribute.MARGIN || att == Attribute.MARGIN_BOTTOM
530             || att == Attribute.MARGIN_LEFT || att == Attribute.MARGIN_RIGHT
531             || att == Attribute.MARGIN_TOP || att == Attribute.WIDTH
532             || att == Attribute.HEIGHT
533             || att == Attribute.PADDING || att == Attribute.PADDING_BOTTOM
534             || att == Attribute.PADDING_LEFT || att == Attribute.PADDING_RIGHT
535             || att == Attribute.PADDING_TOP
536             || att == Attribute.LEFT || att == Attribute.RIGHT
537             || att == Attribute.TOP || att == Attribute.BOTTOM)
538      o = new Length(v);
539    else if (att == Attribute.BORDER_WIDTH || att == Attribute.BORDER_TOP_WIDTH
540             || att == Attribute.BORDER_LEFT_WIDTH
541             || att == Attribute.BORDER_RIGHT_WIDTH
542             || att == Attribute.BORDER_BOTTOM_WIDTH)
543      o = new BorderWidth(v);
544    else
545      o = v;
546    return o;
547  }
548
549  static void addInternal(MutableAttributeSet atts, Attribute a, String v)
550  {
551    if (a == Attribute.BACKGROUND)
552      parseBackgroundShorthand(atts, v);
553    else if (a == Attribute.PADDING)
554      parsePaddingShorthand(atts, v);
555    else if (a == Attribute.MARGIN)
556      parseMarginShorthand(atts, v);
557    else if (a == Attribute.BORDER || a == Attribute.BORDER_LEFT
558             || a == Attribute.BORDER_RIGHT || a == Attribute.BORDER_TOP
559             || a == Attribute.BORDER_BOTTOM)
560      parseBorderShorthand(atts, v, a);
561  }
562
563  /**
564   * Parses the background shorthand and translates it to more specific
565   * background attributes.
566   *
567   * @param atts the attributes
568   * @param v the value
569   */
570  private static void parseBackgroundShorthand(MutableAttributeSet atts,
571                                               String v)
572  {
573    StringTokenizer tokens = new StringTokenizer(v, " ");
574    while (tokens.hasMoreElements())
575      {
576        String token = tokens.nextToken();
577        if (CSSColor.isValidColor(token))
578          atts.addAttribute(Attribute.BACKGROUND_COLOR,
579                            new CSSColor(token));
580      }
581  }
582
583  /**
584   * Parses the padding shorthand and translates to the specific padding
585   * values.
586   *
587   * @param atts the attributes
588   * @param v the actual value
589   */
590  private static void parsePaddingShorthand(MutableAttributeSet atts, String v)
591  {
592    StringTokenizer tokens = new StringTokenizer(v, " ");
593    int numTokens = tokens.countTokens();
594    if (numTokens == 1)
595      {
596        Length l = new Length(tokens.nextToken());
597        atts.addAttribute(Attribute.PADDING_BOTTOM, l);
598        atts.addAttribute(Attribute.PADDING_LEFT, l);
599        atts.addAttribute(Attribute.PADDING_RIGHT, l);
600        atts.addAttribute(Attribute.PADDING_TOP, l);
601      }
602    else if (numTokens == 2)
603      {
604        Length l1 = new Length(tokens.nextToken());
605        Length l2 = new Length(tokens.nextToken());
606        atts.addAttribute(Attribute.PADDING_BOTTOM, l1);
607        atts.addAttribute(Attribute.PADDING_TOP, l1);
608        atts.addAttribute(Attribute.PADDING_LEFT, l2);
609        atts.addAttribute(Attribute.PADDING_RIGHT, l2);
610      }
611    else if (numTokens == 3)
612      {
613        Length l1 = new Length(tokens.nextToken());
614        Length l2 = new Length(tokens.nextToken());
615        Length l3 = new Length(tokens.nextToken());
616        atts.addAttribute(Attribute.PADDING_TOP, l1);
617        atts.addAttribute(Attribute.PADDING_LEFT, l2);
618        atts.addAttribute(Attribute.PADDING_RIGHT, l2);
619        atts.addAttribute(Attribute.PADDING_BOTTOM, l3);
620      }
621    else
622      {
623        Length l1 = new Length(tokens.nextToken());
624        Length l2 = new Length(tokens.nextToken());
625        Length l3 = new Length(tokens.nextToken());
626        Length l4 = new Length(tokens.nextToken());
627        atts.addAttribute(Attribute.PADDING_TOP, l1);
628        atts.addAttribute(Attribute.PADDING_RIGHT, l2);
629        atts.addAttribute(Attribute.PADDING_BOTTOM, l3);
630        atts.addAttribute(Attribute.PADDING_LEFT, l4);
631      }
632  }
633
634  /**
635   * Parses the margin shorthand and translates to the specific margin
636   * values.
637   *
638   * @param atts the attributes
639   * @param v the actual value
640   */
641  private static void parseMarginShorthand(MutableAttributeSet atts, String v)
642  {
643    StringTokenizer tokens = new StringTokenizer(v, " ");
644    int numTokens = tokens.countTokens();
645    if (numTokens == 1)
646      {
647        Length l = new Length(tokens.nextToken());
648        atts.addAttribute(Attribute.MARGIN_BOTTOM, l);
649        atts.addAttribute(Attribute.MARGIN_LEFT, l);
650        atts.addAttribute(Attribute.MARGIN_RIGHT, l);
651        atts.addAttribute(Attribute.MARGIN_TOP, l);
652      }
653    else if (numTokens == 2)
654      {
655        Length l1 = new Length(tokens.nextToken());
656        Length l2 = new Length(tokens.nextToken());
657        atts.addAttribute(Attribute.MARGIN_BOTTOM, l1);
658        atts.addAttribute(Attribute.MARGIN_TOP, l1);
659        atts.addAttribute(Attribute.MARGIN_LEFT, l2);
660        atts.addAttribute(Attribute.MARGIN_RIGHT, l2);
661      }
662    else if (numTokens == 3)
663      {
664        Length l1 = new Length(tokens.nextToken());
665        Length l2 = new Length(tokens.nextToken());
666        Length l3 = new Length(tokens.nextToken());
667        atts.addAttribute(Attribute.MARGIN_TOP, l1);
668        atts.addAttribute(Attribute.MARGIN_LEFT, l2);
669        atts.addAttribute(Attribute.MARGIN_RIGHT, l2);
670        atts.addAttribute(Attribute.MARGIN_BOTTOM, l3);
671      }
672    else
673      {
674        Length l1 = new Length(tokens.nextToken());
675        Length l2 = new Length(tokens.nextToken());
676        Length l3 = new Length(tokens.nextToken());
677        Length l4 = new Length(tokens.nextToken());
678        atts.addAttribute(Attribute.MARGIN_TOP, l1);
679        atts.addAttribute(Attribute.MARGIN_RIGHT, l2);
680        atts.addAttribute(Attribute.MARGIN_BOTTOM, l3);
681        atts.addAttribute(Attribute.MARGIN_LEFT, l4);
682      }
683  }
684
685  /**
686   * Parses the CSS border shorthand attribute and translates it to the
687   * more specific border attributes.
688   *
689   * @param atts the attribute
690   * @param value the value
691   */
692  private static void parseBorderShorthand(MutableAttributeSet atts,
693                                           String value, Attribute cssAtt)
694  {
695    StringTokenizer tokens = new StringTokenizer(value, " ");
696    while (tokens.hasMoreTokens())
697      {
698        String token = tokens.nextToken();
699        if (BorderStyle.isValidStyle(token))
700          {
701            if (cssAtt == Attribute.BORDER_LEFT || cssAtt == Attribute.BORDER)
702              atts.addAttribute(Attribute.BORDER_LEFT_STYLE, token);
703            if (cssAtt == Attribute.BORDER_RIGHT || cssAtt == Attribute.BORDER)
704              atts.addAttribute(Attribute.BORDER_RIGHT_STYLE, token);
705            if (cssAtt == Attribute.BORDER_BOTTOM || cssAtt == Attribute.BORDER)
706              atts.addAttribute(Attribute.BORDER_BOTTOM_STYLE, token);
707            if (cssAtt == Attribute.BORDER_TOP || cssAtt == Attribute.BORDER)
708              atts.addAttribute(Attribute.BORDER_TOP_STYLE, token);
709          }
710        else if (BorderWidth.isValid(token))
711          {
712            BorderWidth w = new BorderWidth(token);
713            if (cssAtt == Attribute.BORDER_LEFT || cssAtt == Attribute.BORDER)
714              atts.addAttribute(Attribute.BORDER_LEFT_WIDTH, w);
715            if (cssAtt == Attribute.BORDER_RIGHT || cssAtt == Attribute.BORDER)
716              atts.addAttribute(Attribute.BORDER_RIGHT_WIDTH, w);
717            if (cssAtt == Attribute.BORDER_BOTTOM || cssAtt == Attribute.BORDER)
718              atts.addAttribute(Attribute.BORDER_BOTTOM_WIDTH, w);
719            if (cssAtt == Attribute.BORDER_TOP || cssAtt == Attribute.BORDER)
720              atts.addAttribute(Attribute.BORDER_TOP_WIDTH, w);
721          }
722        else if (CSSColor.isValidColor(token))
723          {
724            CSSColor c = new CSSColor(token);
725            if (cssAtt == Attribute.BORDER_LEFT || cssAtt == Attribute.BORDER)
726              atts.addAttribute(Attribute.BORDER_LEFT_COLOR, c);
727            if (cssAtt == Attribute.BORDER_RIGHT || cssAtt == Attribute.BORDER)
728              atts.addAttribute(Attribute.BORDER_RIGHT_COLOR, c);
729            if (cssAtt == Attribute.BORDER_BOTTOM || cssAtt == Attribute.BORDER)
730              atts.addAttribute(Attribute.BORDER_BOTTOM_COLOR, c);
731            if (cssAtt == Attribute.BORDER_TOP || cssAtt == Attribute.BORDER)
732              atts.addAttribute(Attribute.BORDER_TOP_COLOR, c);
733          }
734      }
735  }
736}